【问题标题】:C++ Pointers, Linked List ConfusionC++ 指针,链表混淆
【发布时间】:2014-08-01 22:47:47
【问题描述】:

我正在尝试在 C++ 中构建一个链表。我的理解是,我创建的代码应该创建一个节点,然后逐渐将 4 个链接到最后。不幸的是,虽然我希望看到 cout 结果为“12 123 1234 12345”,但我看到的是“12 12 12 12”,而且我主要无法遍历列表 - 它只是崩溃了。

我有以下代码:

struct listNode {

    int val;
    listNode* next;

};


int nodeCount = 0;

listNode* addToEnd(listNode* node) {

    listNode* newNode = new listNode;
    newNode->val = ++nodeCount;
    newNode->next = NULL;

    if (node == NULL) {
        return newNode;
    }

    listNode* current = node;
    cout<<"\n\n";
    do {
        if (current->next == NULL) {
            current->next = newNode;
        }
        cout<<current->val<<"\n";
        current = current->next;
    } while (current->next != NULL);
    cout<<current->val<<endl;

}


int main()
{

    listNode* first = addToEnd(NULL);

    addToEnd(first);
    addToEnd(first);
    addToEnd(first);
    addToEnd(first);

    cout<<"Third: "<<first->next->next->val;

}

感谢任何帮助,因为我无能为力!

【问题讨论】:

    标签: c++ linked-list


    【解决方案1】:

    很明显addToEnd这个函数是错误的

    listNode* addToEnd(listNode* node) {
    
        listNode* newNode = new listNode;
        newNode->val = ++nodeCount;
        newNode->next = NULL;
    
        if (node == NULL) {
            return newNode;
        }
    
        listNode* current = node;
        cout<<"\n\n";
        do {
            if (current->next == NULL) {
                current->next = newNode;
            }
            cout<<current->val<<"\n";
            current = current->next;
        } while (current->next != NULL);
        cout<<current->val<<endl;
    
    }
    

    假设列表已经包含两个节点,并考虑函数内部的 do-while 循环。起初current_next != null 所以执行下面的语句

            current = current->next;
    

    现在 current 指向第二个节点。它的数据成员next 等于NULL。所以循环的条件

        } while (current->next != NULL);
    

    为 false,不会重复任何迭代。所以我们什么也没添加。

    如果 node 不等于 NULL,该函数也不返回任何内容。

    按如下方式重写函数

    listNode* addToEnd( listNode* node ) 
    {
    
        listNode* newNode = new listNode { ++nodeCount, NULL };
    
        if ( node == NULL) return newNode;
    
        listNode* current = node;
    
        while ( current->next != NULL ) current = current->next;
    
        current->next = newNode;
    
        return newNode;
        // or
        //return node;    
    }
    

    考虑到这个声明

    cout<<"Third: "<<first->next->next->val;
    

    仅输出第三个节点的值。 如果你想输出所有你应该写的列表

    for ( listNode *current = first; current; current = current->next ) 
    {
        std::cout << current->val << ' ';
    }
    std::cout << std::endl;
    

    顺便说一句,使用我的函数,你可以在 main 中编写,例如以下方式:)

    listNode* first;
    
    addToEnd( addToEnd( addToEnd( addToEnd( first  = addToEnd( NULL ) ) ) ) );
    

    【讨论】:

    • 为什么每次都准确返回传入的内容?
    • @Josh 其实返回新创建的节点会更好。
    • 其实我喜欢不变的“这个函数返回列表的头部”。这意味着调用者可以写head = addToEnd(head);,而不必担心列表之前是否为空。
    • @VladfromMoscow 节点不是新创建的,它是用户传入的列表中某处的节点。Ben,我们不能保证我们会得到列表的头部,我们所知道的是它是来自某个地方的一个节点。
    • @Ben Voigt 如果每个节点都插入到列表的开头,我会同意你的看法。
    【解决方案2】:

    使用 for 循环将您带到最后一个节点而不是 while,然后将新节点分配到循环的 OUTSIDE。尝试在内部执行会导致无限循环(并使代码更难阅读):

    listNode* current;
    for(current = node; current->next != NULL; current = current->next) ;
    current->next = newNode;
    

    您还忘记在函数末尾返回newNode

    【讨论】:

      【解决方案3】:

      您正在使用非void 返回类型的函数结束。您不使用返回值这一事实并不能解决问题。

      标准中的 6.6.3 说:

      从函数末尾流出相当于没有值的return;这会在返回值的函数中导致未定义的行为。

      【讨论】:

      • 我记得,如果返回值不在C(这是标签之一)中使用是可以的,但代码绝对不是C。
      • @chris:问题的第一句话说代码是C++。
      • @Deduplicator:Chris 是对的,C 中的规则不同。 C99 中的 6.9.1 表示“如果到达终止函数的 }并且调用者使用函数调用的值,则行为未定义。”
      • @Deduplicator:C++不需要考虑丢失原型等情况,它的类型检查要严格得多。
      【解决方案4】:

      没有返回语句以防万一检查if(node==null)的if条件失败..

      【讨论】:

        【解决方案5】:

        在您的问题中使用递归函数是否违反规则?

        为什么不...

        void addToEnd(listNode* node){
            if(node == NULL){
                *node = new listNode;
                node->next = NULL;
                node->val = ++nodeCount;
            }else{
                addToEnd(node->next);
            }
            return;
        }
        
        int main(){
            listNode* first = NULL;
            addToEnd(first); // 1
            addToEnd(first); // 2
            addToEnd(first); // 3
            addToEnd(first); // 4
            addToEnd(first); // Linked list is now 5 long
        }
        

        【讨论】:

          【解决方案6】:

          这就是我将如何将五个节点添加到包含节点计数的链表的编码方式。如果有人有建议,欢迎。

          #include <iostream>
          #include <cstdlib>
          
          using namespace std;
          
          struct listNode{
           int val;
           listNode* next;
          };
          
          listNode* addToEnd(listNode*, int);
          
          int main()
          {
            listNode* first = NULL;
            listNode* temp;
            int nodeCount = 1;
          
            for(int i = 0; i < 5; i++){
               first = addToEnd(first, nodeCount);
               nodeCount++;
            }
          
            temp = first;
          
            while(temp){
               cout << temp->val << ' ';
               temp = temp->next;
            }
          
            temp = first;
                                         //Deallocate memory
            while(temp){                 //could do memory deallocation while displaying 
               nodeToDelete = temp;      //the value of nodeCount but wanted to illustrate  
                                         //both methods individually
               temp = temp->next;
          
               delete nodeToDelete;   
            }  
          
            first = NULL;                //eliminate hanging pointer
          
            return 0;
          }
          
          listNode* addToEnd(listNode* node, int nodeCount) 
          {
          
            listNode* newNode = new (nothrow) listNode;
            listNode* current = node;
          
            if(newNode){
               newNode->val = nodeCount;
               newNode->next = NULL;
               if (node == NULL)        
                  node = newNode;       
          
               else{          
                  while (current->next != NULL) 
                     current = current->next;
          
                     current->next = newNode;          
               }
            }
            else
               cout << "error allocationg memory" << endl;
          
            return node;
          }
          

          【讨论】:

            猜你喜欢
            • 2013-07-07
            • 1970-01-01
            • 2019-08-05
            • 1970-01-01
            • 2010-09-25
            • 2011-09-04
            • 2016-11-08
            • 2018-10-07
            • 1970-01-01
            相关资源
            最近更新 更多