简体   繁体   English

链表头双指针传递

[英]Linked list head double pointer passing

I have seen this in some book/ tutorial. 我在一些书/教程中看到了这一点。

When you pass in the head pointer (of linked list) into a function, you need to pass it as a double pointer. 将头指针(链接列表)传入函数时,需要将其作为双指针传递。

For eg: // This is to reverse a linked list where head points to first node. 例如://这是为了反转头部指向第一个节点的链表。

void nReverse(digit **head)
{
    digit *prev=NULL;
    digit *curr=*head;
    digit *next;

    while(curr!=NULL)
    {
        next=curr->next;
        curr->next=prev;
        prev=curr;
        curr=next;
    }
    *head=prev;
    return;
}

This works fine. 这很好用。

It also works when I use single pointer like, 当我使用单指针时,它也有效,

void nReverse(digit *head)
{
    digit *prev=NULL;
    digit *curr=head;
    digit *next;

    while(curr!=NULL)
    {
        next=curr->next;
        curr->next=prev;
        prev=curr;
        curr=next;
    }
    head=prev;
    return;
}

I tried printing the list by using the head pointer. 我尝试使用头指针打印列表。 Both the functions work fine. 这两个功能都很好。

Am I missing something ? 我错过了什么吗?

Thanks, 谢谢,

This is very C-like code, not C++. 这是非常类似C的代码,而不是C ++。

Basically, when something is passed by-value the function operates on a copy of the data: 基本上,当按值传递某些内容时,该函数会对数据副本进行操作:

void foo(int i)
{
    i = 5; // copy is set to 5
}

int x = 7;
foo(x);
// x is still 7

In C, you instead pass a pointer to the variable, and can change it that way: 在C中,您改为传递指向变量的指针,并可以这样改变它:

void foo(int* i)
{
    *i = 5; // whatever i points to is set to 5
}

int x = 7;
foo(&x);
// x is 5

For you, instead of an int it's a digit* . 对你而言,它不是一个int ,而是一个digit* (Resulting in a pointer to pointer.) (导致指向指针。)


In C++, references were introduced. 在C ++中,引入了引用。 A reference is an alias to another object. 引用是另一个对象的别名。 So you'd do something like this: 所以你会做这样的事情:

void foo(int& i) // i is an alias to another value
{
    i = 5; // x is set to 5
}

int x = 7;
foo(x); // pass x as alias, not address of x.
// x is 5

A reference is generally preferred, since it enforces that you actually refer to an object, and simplifies both calling and operating code. 引用通常是首选,因为它强制您实际引用对象,并简化调用和操作代码。

Of course in C++ you wouldn't implement a list yourself, you'd use std::list . 当然在C ++中你不会自己实现一个列表,你可以使用std::list

That last head=prev; 最后一个head=prev;上一个head=prev; does not change the passed pointer's value in the second example. 不会更改第二个示例中传递的指针的值。 Whether or not that line is necessary for the purposes of this function is up to you. 对于此功能而言,该行是否必要取决于您自己。 But there is a difference. 但是有区别。

How did you test that it "worked fine"? 你是如何测试它“工作正常”的? Were you able to iterate the list and print out the node's values and see that they had in fact been reversed? 您是否能够迭代列表并打印出节点的值并看到它们实际上已被反转? The first function (presumably called like nReverse(&list); changes what list points to, the second do not (so for the second how do you know which node is the beginning of the list, after all it was just changed...). 第一个函数(可能称为nReverse(&list); 更改 list指向的内容,第二个函数nReverse(&list); 更改 (因此对于第二个函数,您如何知道哪个节点是列表的开头,毕竟它只是更改了...) 。

In the first example, what you passed in still points to the "beginning" of the list. 在第一个示例中,您传入的内容仍然指向列表的“开头”。

In the second example, it points to the end of the list (which was the beginning when you started, but has since moved). 在第二个示例中,它指向列表的末尾(这是您开始时的开始,但此后已移动)。

The reason for the double indirection is so nReverse can modify the caller's pointer, since after reversing the list, the head of the list is now a different node. 双重间接的原因是nReverse可以修改调用者的指针,因为在反转列表之后,列表的头部现在是一个不同的节点。

In the second version, you are modifying the copy of head that is local to the function, so the caller still has a reference to the old head node, which is now the tail. 在第二个版本中,您正在修改函数本地的head副本,因此调用者仍然具有对旧头节点的引用,现在它是尾部。

The reason for having double pointer passing (the first example) is that you want to change the head of the list. 双指针传递的原因(第一个例子)是你想要改变列表的头部。 Since you are reversing the list, the head should point to the last element of the list after you have done the reversing. 由于您正在反转列表,因此在完成反转后,头应指向列表的最后一个元素。

digit* list; 
// initialize list
nReverse(&list); 
// now list is pointing to the last element of the chain (and not the first)

If you don't use double pointers, then list will still point to the original first element which next now points to NULL because its the last element after the reversing. 如果你不使用双指针,那么list仍将指向原来的第一个元素,下一个现在指向NULL,因为它是反转后的最后一个元素。 So you loose all your other elements. 所以你放弃了所有其他元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM