2016-05-17 17 views
2

构建链接列表结构时。我已经学会了正确的做法,但我不知道为什么更简单的方法不起作用。我搜索了互联网,我买了一本书,我玩了代码和理论,我终于说它退出,并愿意处理我的问题,如果我只是错过了一些消极的东西。所以这里是:为什么在构建链接列表时我必须指向一个指针C++

#include <bits/stdc++.h> 
using namespace std; 


struct Node{ 
    int data; 
    Node* next; 

    // Constructor 
    Node(int data) 
    { 
     this->data = data; 
     next = NULL; 
    } 
}; 

// Class to represent Red-Black Tree 
class LinkedList{ 
private: 
    Node* root; 
public: 
    // Constructor 
    LinkedList() { root = NULL; } 
    //insert new value into list 
    void insert(const int n); 
    //print all values from root to end; 
    void print(); 
}; 

// Function to insert a new node with given data 
void LinkedList::insert(const int data){ 
    Node** pp = &root; 
    while (*pp) 
     pp = &((*pp)->next); 
    *pp = new Node(data); 
} 

void LinkedList::print(){ 
    Node** pp = &root; 
    while (*pp){ 
     cout << (*pp)->data << " "; 
     pp = &((*pp)->next); 
    } 
    cout << endl; 
} 



int main(){ 
    LinkedList ll; 
    ll.insert(5); 
    ll.insert(2); 
    ll.insert(22); 
    ll.print(); 

    return 0; 
} 

很简单的东西,它运行的很好。但是,这是一个问题。因为我不知道为什么我不能做到这一点:

void LinkedList::insert(const int data){ 
    Node* pp = root; 
    while (pp) 
     pp = pp->next; 
    pp = new Node(data); 
} 

应该做同样的事情我看到指针在我的头上的方式。当我在纸上写下地址/内容对时,它仍然有意义。

谢谢, -Connor。

+0

如果'root'是空会发生什么? – vu1p3n0x

+0

你会 - 如果你只做'pp = pp-> next;'。在附注中,您不应该包含''。相反,请按照所用功能的文档中的说明包含适当的标题。 – SergeyA

+0

vu1p3n0x - 如果root为空,'(pp)'应该可以捕捉到。 SergeyA - 没有任何回报。 但也许这是所有返回到根为空时的问题。但我不明白为什么这很重要。不应pp也为空,因此while循环永远不会被调用。 –

回答

2
void LinkedList::insert(const int data){ 
    Node* pp = root; 
    while (pp) 
     pp = pp->next; 
    pp = new Node(data); 
} 

此代码实际上没有做任何事情。将pp设置为某个特定值会遇到很多麻烦,只能忽略该值并重新分配pp其他值。然后它返回,pp超出范围,并且它分配给它的值永远丢失。

让我们通过它逐行:

void LinkedList::insert(const int data){ 
    Node* pp = root; 

在点,pp是等于root一个局部变量。

while (pp) 
    pp = pp->next; 

,直到它使用的是列表的末尾这改变的pp值。所以我们已经完成了整个列表,只做最后的pp设置为NULL

pp = new Node(data); 

不,我们创建一个新的Node和改变pp的价值指向新Node。所以我们花费了所有的麻烦,让pp指向最后一个节点只是经过它,然后改变它指向一个新的节点。

} 

现在我们回到,pp超出范围,和我们没有新Node做什么事情。

您还可以看到:

void LinkedList::insert(const int data){ 
    Node* pp = root; 
    while (pp) 
     pp = pp->next; 
    pp = new Node(data); 
} 

相当于(假设它不会永远运行):

void LinkedList::insert(const int data){ 
    Node* pp = root; 
    pp = NULL; 
    pp = new Node(data); 
} 

即相当于:

void LinkedList::insert(const int data){ 
    Node* pp = NULL; 
    pp = new Node(data); 
} 

哪相当于:

void LinkedList::insert(const int data){ 
    Node* pp = new Node(data); 
} 

即相当于:

void LinkedList::insert(const int data){ 
    new Node(data); 
} 

这显然会创建一个新Node并及时泄漏了。

+0

你不能做的最后一行'PP->未来=新节点(数据);'因为此时PP为NULL,并且没有下一个指针,所以你需要你到年底之前,所以你可以指定停止最后一个指向新节点的指针。 –

+0

如果root为null,则不会发生崩溃 - while循环根本不会被输入......整体的本质是,新节点仅仅被分配给一个局部变量。除此之外,很好的答案,+1。 – Aconcagua

+0

谢谢。你是对的。我确定了答案。 –

1

我不喜欢做的这样两种:

void LinkedList::insert(const int data){ 
    Node** pp = &root; 
    while (*pp) 
     pp = &((*pp)->next); 
    *pp = new Node(data); 
} 

我会用是:

// returns the last node or NULL on failure 
bool LinkedList::insert(const int data){ 
    Node* pp = root; 

    if (!pp){ // if it is an empty list 
     root = new Node(data); // assign it to something 
     return root; // convert to bool and return - false if new failed 
    } 

    while (pp->next) // check if we have a next node 
     pp = pp->next; // we do have a next node so go there 

    // at this point pp->next will be NULL 

    pp->next = new Node(data); // assign it to something 
    return pp->next; // convert to bool and return - false if new failed 
} 
+0

那么你想如何将一个元素插入一个空列表呢? – Aconcagua

+1

说实话,这个插入仅仅是为了插入到链表(或尾)的末尾而非常低效。只需存储一个尾指针并优化插入,以使尾巴接近这个新节点,从而摆脱当前的问题。 – SenselessCoder

+0

@SenselessCoder好点 - 将适用于整个问题,但不仅仅是这个答案... – Aconcagua

1

认为,一个指针是简单的存储内存地址的变量类型。例如,int *只是一个存储另一个int变量地址的变量(“a box”)。

当您在“插入”功能做:

Node* pp; 

页是你的函数的地址存储到Node对象的当地变量。当你从函数返回时,局部变量被销毁。

当你这样做:

Node ** pp; 

你定义还存储地址的局部变量,而不是一个Node对象,而是指向一个Node对象,那就是另一种“中间盒”即将地址存储到节点对象。

最后,当你这样做:

pp = &((*pp)->next); 

局部变量,它会被销毁,当你函数返回时,商店的“下一个”成员的地址。不喜欢,当你做:

pp = pp->next 

您分配给“PP” 相同存储在“下一个”地址(如果下一个是0×1234,即是代表地址的对象的简单值,pp将得到相同的值0x1234),在列表的最后一个对象中将为NULL。

随着句子:

*pp = new Node(data); 

“PP”的内容是另一个指针到节点对象(不直接的对象)的地址,在这种情况下,这是“下一个地址“指针(而不是”下一个“指针的值),并且当您为pp的内容分配”新节点(数据)“时,您将对象地址分配给”下一个“指针,该指针是你的列表对象,而不是本地变量,你得到的是将你的新节点链接到你的列表。

为了更好地理解指针,你可以在纸上画你的变量结构,画的指针作为存储地址的盒子,并有自己的地址,因为这是变量。

相关问题