【问题标题】:Simple linked list in C++C++中的简单链表
【发布时间】:2014-04-04 04:32:21
【问题描述】:

我即将创建一个可以插入和显示到现在的链接:

struct Node {
    int x;
    Node *next;
};

这是我的初始化函数,只会为第一个 Node 调用:

void initNode(struct Node *head, int n){
    head->x = n;
    head->next = NULL;
}

添加Node,我认为我的链表不能正常工作的原因在于这个函数:

void addNode(struct Node *head, int n){
    struct Node *NewNode = new Node;
    NewNode-> x = n;
    NewNode -> next = head;
    head = NewNode;
}

我的main 功能:

int _tmain(int argc, _TCHAR* argv[])
{
    struct Node *head = new Node;

    initNode(head, 5);
    addNode(head, 10);
    addNode(head, 20);
    return 0;
}

让我按照我认为可行的方式运行该程序。首先,我将头部 Node 初始化为 Node,如下所示:

head = [ 5 |  NULL ]

然后我添加一个 n = 10 的新节点并将 head 作为我的参数传递。

新节点 = [ x | next ] next 指向头部。然后我改变了head指向NewNode的位置,因为NewNode现在是LinkedList中的第一个Node。

为什么这不起作用?我将不胜感激任何可以使我朝着正确方向前进的提示。我觉得 LinkedList 有点难理解。

当我打印这个时,它只返回 5:

【问题讨论】:

  • 更多的是 C 而不是 C++。您应该将链表封装在一个类中。并且指针Node *head应该是类内部的私有成员变量,直接指向第一个节点(实际的方式是你必须为指向下一个元素的一个虚拟节点分配内存。所以你浪费内存,逻辑更复杂并且不代表模型的想法)。如果您需要一些示例代码,请告诉我。
  • 你能给我举个例子吗?

标签: c++ linked-list


【解决方案1】:

这是我在这种情况下能想到的最简单的例子,没有经过测试。请考虑这使用了一些不好的做法,并且与您通常使用 C++ 的方式不同(初始化列表、声明和定义的分离等)。但这是我无法在此处涵盖的主题。

#include <iostream>
using namespace std;

class LinkedList{
    // Struct inside the class LinkedList
    // This is one node which is not needed by the caller. It is just
    // for internal work.
    struct Node {
        int x;
        Node *next;
    };

// public member
public:
    // constructor
    LinkedList(){
        head = NULL; // set head to NULL
    }

    // destructor
    ~LinkedList(){
        Node *next = head;
        
        while(next) {              // iterate over all elements
            Node *deleteMe = next;
            next = next->next;     // save pointer to the next element
            delete deleteMe;       // delete the current entry
        }
    }
    
    // This prepends a new value at the beginning of the list
    void addValue(int val){
        Node *n = new Node();   // create new Node
        n->x = val;             // set value
        n->next = head;         // make the node point to the next node.
                                //  If the list is empty, this is NULL, so the end of the list --> OK
        head = n;               // last but not least, make the head point at the new node.
    }

    // returns the first element in the list and deletes the Node.
    // caution, no error-checking here!
    int popValue(){
        Node *n = head;
        int ret = n->x;

        head = head->next;
        delete n;
        return ret;
    }

// private member
private:
    Node *head; // this is the private member variable. It is just a pointer to the first Node
};

int main() {
    LinkedList list;

    list.addValue(5);
    list.addValue(10);
    list.addValue(20);

    cout << list.popValue() << endl;
    cout << list.popValue() << endl;
    cout << list.popValue() << endl;
    // because there is no error checking in popValue(), the following
    // is undefined behavior. Probably the program will crash, because
    // there are no more values in the list.
    // cout << list.popValue() << endl;
    return 0;
}

我强烈建议您阅读一些有关 C++ 和面向对象编程的知识。一个好的起点可能是:http://www.galileocomputing.de/1278?GPP=opoo

编辑:添加了弹出功能和一些输出。如您所见,程序推送 3 个值 5、10、20,然后将它们弹出。之后顺序颠倒,因为此列表在堆栈模式下工作(LIFO,后进先出)

【讨论】:

  • 呸,一个连基本测试都没有的例子,那不是例子!
  • 正常编译退出。这还不够吗?我认为他需要一个非常简单的示例,因为他不了解 OO C++。如果他对那个主题感兴趣(如果他想成为 C++ 程序员,他应该会),他必须学习比这 30 节更多的东西。
  • 可能,但如果他需要更多,这个:pastebin.com/yGh8hjnx 可以用g++ -o ll+ ll.cc 编译,证明你的代码中没有错误(我可以很容易找到:)) , 介绍了游标的基本概念(使列表完全有用:))并且似乎有效。
  • 是的,当然,要成为一个真正的列表并使它变得有用,还需要更多的东西(在这种情况下,您的示例更有用,+1)。但也许对于初学者来说更容易理解。
  • 我不确定我应该接受什么答案作为“正确”,因为每个答案都对我有帮助。发生这种情况时,这个论坛的处理方法是什么?
【解决方案2】:

您应该参考头指针。否则指针修改在函数外是不可见的。

void addNode(struct Node *&head, int n){
    struct Node *NewNode = new Node;
 NewNode-> x = n;
 NewNode -> next = head;
 head = NewNode;
}

【讨论】:

    【解决方案3】:

    我会加入战斗。太久没写C了。再说了,反正这里也没有完整的例子。 OP 的代码基本上是 C,所以我继续让它与 GCC 一起工作。

    问题之前已经介绍过; next 指针没有被推进。这就是问题的症结所在。

    我还借此机会提出了修改建议;而不是有两个函数到malloc,我把它放在initNode(),然后使用initNode()malloc 两者(malloc 是“C 新”,如果你愿意的话)。我更改了initNode() 以返回一个指针。

    #include <stdlib.h>
    #include <stdio.h>
    
    // required to be declared before self-referential definition
    struct Node;
    
    struct Node {
        int x;
        struct Node *next;
    };
    
    struct Node* initNode( int n){
        struct Node *head = malloc(sizeof(struct Node));
        head->x = n;
        head->next = NULL;
        return head;
    }
    
    void addNode(struct Node **head, int n){
     struct Node *NewNode = initNode( n );
     NewNode -> next = *head;
     *head = NewNode;
    }
    
    int main(int argc, char* argv[])
    {
        struct Node* head = initNode(5);
        addNode(&head,10);
        addNode(&head,20);
        struct Node* cur  = head;
        do {
            printf("Node @ %p : %i\n",(void*)cur, cur->x );
        } while ( ( cur = cur->next ) != NULL );
    
    }
    

    编译:gcc -o ll ll.c

    输出:

    Node @ 0x9e0050 : 20
    Node @ 0x9e0030 : 10
    Node @ 0x9e0010 : 5
    

    【讨论】:

      【解决方案4】:

      下面是一个示例链表

          #include <string>
          #include <iostream>
      
          using namespace std;
      
      
          template<class T>
          class Node
          {
          public:
              Node();
              Node(const T& item, Node<T>* ptrnext = NULL);
              T value;
              Node<T> * next;
          };
      
          template<class T>
          Node<T>::Node()
          {
              value = NULL;
              next = NULL;
          }
          template<class T>
          Node<T>::Node(const T& item, Node<T>* ptrnext = NULL)
          {
              this->value = item;
              this->next = ptrnext;
          }
      
          template<class T>
          class LinkedListClass
          {
          private:
              Node<T> * Front;
              Node<T> * Rear;
              int Count;
          public:
              LinkedListClass();
              ~LinkedListClass();
              void InsertFront(const T Item);
              void InsertRear(const T Item);
              void PrintList();
          };
          template<class T>
          LinkedListClass<T>::LinkedListClass()
          {
              Front = NULL;
              Rear = NULL;
          }
      
          template<class T>
          void LinkedListClass<T>::InsertFront(const T  Item)
          {
              if (Front == NULL)
              {
                  Front = new Node<T>();
                  Front->value = Item;
                  Front->next = NULL;
                  Rear = new Node<T>();
                  Rear = Front;
              }
              else
              {
                  Node<T> * newNode = new Node<T>();
                  newNode->value = Item;
                  newNode->next = Front;
                  Front = newNode;
              }
          }
      
          template<class T>
          void LinkedListClass<T>::InsertRear(const T  Item)
          {
              if (Rear == NULL)
              {
                  Rear = new Node<T>();
                  Rear->value = Item;
                  Rear->next = NULL;
                  Front = new Node<T>();
                  Front = Rear;
              }
              else
              {
                  Node<T> * newNode = new Node<T>();
                  newNode->value = Item;
                  Rear->next = newNode;
                  Rear = newNode;
              }
          }
          template<class T>
          void LinkedListClass<T>::PrintList()
          {
              Node<T> *  temp = Front;
              while (temp->next != NULL)
              {
                  cout << " " << temp->value << "";
                  if (temp != NULL)
                  {
                      temp = (temp->next);
                  }
                  else
                  {
                      break;
                  }
              }
          }
      
          int main()
          {
              LinkedListClass<int> * LList = new LinkedListClass<int>();
              LList->InsertFront(40);
              LList->InsertFront(30);
              LList->InsertFront(20);
              LList->InsertFront(10);
              LList->InsertRear(50);
              LList->InsertRear(60);
              LList->InsertRear(70);
              LList->PrintList();
          }
      

      【讨论】:

      • 析构函数怎么样?
      【解决方案5】:

      这两个函数都是错误的。首先,函数initNode 有一个令人困惑的名称。它应该被命名为例如initList,并且不应该执行addNode的任务。也就是说,它不应该向列表中添加值。

      其实initNode函数没有任何意义,因为在定义头部的时候就可以完成list的初始化:

      Node *head = nullptr;
      

      Node *head = NULL;
      

      因此您可以从您的列表设计中排除函数initNode

      同样在您的代码中,无需为结构 Node 指定详细类型名称,即在名称 Node 之前指定关键字 struct。

      函数addNode将改变head的原始值。在您的函数实现中,您只更改作为参数传递给函数的 head 副本。

      函数可能如下所示:

      void addNode(Node **head, int n)
      {
          Node *NewNode = new Node {n, *head};
          *head = NewNode;
      }
      

      或者如果您的编译器不支持新的初始化语法,那么您可以编写

      void addNode(Node **head, int n)
      {
          Node *NewNode = new Node;
          NewNode->x = n;
          NewNode->next = *head;
          *head = NewNode;
      }
      

      或者不使用指向指针的指针,您可以使用指向 Node.js 的指针的引用。例如,

      void addNode(Node * &head, int n)
      {
          Node *NewNode = new Node {n, head};
          head = NewNode;
      }
      

      或者你可以从函数中返回一个更新的头部:

      Node * addNode(Node *head, int n)
      {
          Node *NewNode = new Node {n, head};
          head = NewNode;
          return head;
      }
      

      然后在main 写:

      head = addNode(head, 5);
      

      【讨论】:

        【解决方案6】:

        addNode 函数需要能够更改head。正如现在所写的那样,只需更改局部变量head(一个参数)。

        把代码改成

        void addNode(struct Node *& head, int n){
            ...
        }
        

        会解决这个问题,因为现在head 参数是通过引用传递的,并且被调用的函数可以改变它。

        【讨论】:

          【解决方案7】:

          head 在 main 内部定义如下。

          struct Node *head = new Node;
          

          但您只更改了 addNode()initNode() 函数中的头部。更改不会反映在主服务器上。

          将头部声明为全局,不要将其传递给函数。

          功能应该如下。

          void initNode(int n){
              head->x = n;
              head->next = NULL;
          }
          
          void addNode(int n){
              struct Node *NewNode = new Node;
              NewNode-> x = n;
              NewNode->next = head;
              head = NewNode;
          }
          

          【讨论】:

            【解决方案8】:

            我认为,为了保证列表中每个节点的深度链接,addNode方法必须是这样的:

            void addNode(struct node *head, int n) {
              if (head->Next == NULL) {
                struct node *NewNode = new node;
                NewNode->value = n;
                NewNode->Next = NULL;
                head->Next = NewNode;
              }
              else 
                addNode(head->Next, n);
            }
            

            【讨论】:

              【解决方案9】:

              用途:

              #include<iostream>
              
              using namespace std;
              
              struct Node
              {
                  int num;
                  Node *next;
              };
              
              Node *head = NULL;
              Node *tail = NULL;
              
              void AddnodeAtbeggining(){
                  Node *temp = new Node;
                  cout << "Enter the item";
                  cin >> temp->num;
                  temp->next = NULL;
                  if (head == NULL)
                  {
                      head = temp;
                      tail = temp;
                  }
                  else
                  {
                      temp->next = head;
                      head = temp;
                  }
              }
              
              void addnodeAtend()
              {
                  Node *temp = new Node;
                  cout << "Enter the item";
                  cin >> temp->num;
                  temp->next = NULL;
                  if (head == NULL){
                      head = temp;
                      tail = temp;
                  }
                  else{
                      tail->next = temp;
                      tail = temp;
                  }
              }
              
              void displayNode()
              {
                  cout << "\nDisplay Function\n";
                  Node *temp = head;
                  for(Node *temp = head; temp != NULL; temp = temp->next)
                      cout << temp->num << ",";
              }
              
              void deleteNode ()
              {
                  for (Node *temp = head; temp != NULL; temp = temp->next)
                      delete head;
              }
              
              int main ()
              {
                  AddnodeAtbeggining();
                  addnodeAtend();
                  displayNode();
                  deleteNode();
                  displayNode();
              }
              

              【讨论】:

              • 您能否在答案中添加更多解释?
              • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
              【解决方案10】:

              代码中有一个错误:

              void deleteNode ()
              {
                  for (Node * temp = head; temp! = NULL; temp = temp-> next)
                      delete head;
              }
              

              这是必须的:

              for (; head != NULL; )
              {
                  Node *temp = head;
                  head = temp->next;
              
                  delete temp;
              }
              

              【讨论】:

                【解决方案11】:

                这是我的实现。

                #include <iostream>
                
                using namespace std;
                
                template< class T>
                struct node{
                    T m_data;
                    node* m_next_node;
                
                    node(T t_data, node* t_node) :
                        m_data(t_data), m_next_node(t_node){}
                
                    ~node(){
                        std::cout << "Address :" << this << " Destroyed" << std::endl;
                    }
                };
                
                template<class T>
                class linked_list {
                public:
                    node<T>* m_list;
                
                    linked_list(): m_list(nullptr){}
                
                    void add_node(T t_data) {
                        node<T>* _new_node = new node<T>(t_data, nullptr);
                        _new_node->m_next_node = m_list;
                        m_list = _new_node;
                    }
                
                
                    void populate_nodes(node<T>* t_node) {
                        if  (t_node != nullptr) {
                            std::cout << "Data =" << t_node->m_data
                                      << ", Address =" << t_node->m_next_node
                                      << std::endl;
                            populate_nodes(t_node->m_next_node);
                        }
                    }
                
                    void delete_nodes(node<T>* t_node) {
                        if (t_node != nullptr) {
                            delete_nodes(t_node->m_next_node);
                        }
                        delete(t_node);
                    }
                
                };
                
                
                int main()
                {
                    linked_list<float>* _ll = new linked_list<float>();
                
                    _ll->add_node(1.3);
                    _ll->add_node(5.5);
                    _ll->add_node(10.1);
                    _ll->add_node(123);
                    _ll->add_node(4.5);
                    _ll->add_node(23.6);
                    _ll->add_node(2);
                
                    _ll->populate_nodes(_ll->m_list);
                
                    _ll->delete_nodes(_ll->m_list);
                
                    delete(_ll);
                
                    return 0;
                }
                

                【讨论】:

                  【解决方案12】:

                  使用节点类和链表类的链表

                  这只是一个示例,代码中解释了链接列表、附加功能和打印链接列表的完整功能

                  代码:

                  #include<iostream>
                  using namespace std;
                  

                  节点类

                  class Node{
                      public:
                      int data;
                      Node* next=NULL;
                      Node(int data)
                          {
                              this->data=data;
                  
                  
                          }   
                      };
                  

                  链接列表类命名为 ll

                  class ll{
                      public:
                          Node* head;
                  
                  ll(Node* node)
                      {
                          this->head=node;
                      }
                  
                  void append(int data)
                      {
                          Node* temp=this->head;
                          while(temp->next!=NULL)
                              {
                                  temp=temp->next;
                              }
                          Node* newnode= new Node(data);
                          // newnode->data=data;
                          temp->next=newnode;
                      }
                  void print_list()
                      {   cout<<endl<<"printing entire link list"<<endl;
                          Node* temp= this->head;
                          while(temp->next!=NULL)
                              {
                                  cout<<temp->data<<endl;
                                  temp=temp->next;
                              }
                          cout<<temp->data<<endl;;
                  
                      }
                  };
                  

                  主要功能

                  int main()
                  {
                    cout<<"hello this is an example of link list in cpp using classes"<<endl;
                    ll list1(new Node(1));
                    list1.append(2);
                    list1.append(3);
                    list1.print_list();
                    }
                  
                  thanks ❤❤❤
                  

                  截图https://i.stack.imgur.com/C2D9y.jpg

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2010-11-08
                    • 2011-11-10
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-08-29
                    • 2011-09-17
                    相关资源
                    最近更新 更多