C++ 我如何理解链表?

C++ 我如何理解链表?,c++,linked-list,C++,Linked List,我试图了解它们是如何工作的,但我遇到了很多困难。是否有人愿意直观地解释它们,或者提供他们认为对刚刚开始讨论这个话题的人有用的资源 假设我有这个: struct node { int nodeNum; nodes *next; } 要创建“head”节点,我将执行以下操作:node*head=new节点使我的链接列表现在看起来像。派遣后: head->nodeNum = 10; head->next = NULL; 我们有。现在,如果我想写一个插入节点的函数,我可以写:

我试图了解它们是如何工作的,但我遇到了很多困难。是否有人愿意直观地解释它们,或者提供他们认为对刚刚开始讨论这个话题的人有用的资源

假设我有这个:

struct node
{
   int nodeNum;
   nodes *next;
}
要创建“head”节点,我将执行以下操作:
node*head=new节点使我的链接列表现在看起来像。派遣后:

head->nodeNum = 10;
head->next = NULL;
我们有。现在,如果我想写一个插入节点的函数,我可以写:

void insert(node *previousNode, int num)
{
    previousNode = new node;
    previousNode->nodeNum = num;
    previousNode->next = NULL;
}
所以如果我要做,比如说,
insert(head,20)我的新列表看起来像什么

如果一切正常,如何使用此信息搜索和/或从列表中删除节点?遍历节点并不像下面描述的那样直观。这是怎么回事


如果你能提供任何建议,让这个话题更容易理解,那就太好了。谢谢大家的帮助

您使用的术语让您感到困惑。希望这个类比不会让你更加困惑。本质上,把链表想象成一组可怕的门道,一旦你进入一个门道,它就会在你身后关闭,你只能看到那个房间里有什么,或者去下一个房间。从这个走廊的外面,你只知道入口在哪里,而不知道里面是什么

所以,从链表结构之外,你所知道的只是入口,一些指针
ll_node*head
头的内部是一些数据和指向链接列表中下一个节点的指针。遍历该链表非常简单,只需从走廊入口开始,
head
,然后一次进入一个走廊,直到找到要查找的节点

ll_node *current_location = head;
while (current_location != NULL)
{
   // if we are at the node that you were hoping to reach, exit.
   if (current_location->nodeNum == target_data_im_looking_for)
   {
      break;
   }
   // this isn't the node you're looking for, go to the next one.
   current_location = current_location->next;
}

类似地,插入节点应该遍历到链表的末尾(直到
current_location->next==NULL
),并用您创建的新
ll_节点的内存位置替换最后一个元素的下一个指针。我不会为您实现这一点,这样您就有机会学习了,但这里有足够的内容可以达到您想要的目的。

您的插入函数无法正常工作;它只创建一个新节点,而不将其添加到列表中,并在函数返回时丢失它(导致内存泄漏):

head -> 10 -> NULL     becomes    head -> 10 -> NULL
                                  (lost)  20 -> NULL
相反,它应该将列表的旧尾部链接到新节点,并在旧节点之后插入新节点:

void insert(node * prev, int num) {
    node * new_node = new node;
    new_node->nodeNum = num;
    new_node->next = prev->next;  // add the old tail after the new node
    prev->next = new_node;        // add the new node after the old node
}

insert(head, 20); // insert 20 after the head
// head -> 10 -> NULL   becomes    head -> 20 -> 10 -> NULL
如何使用此信息从列表中搜索和/或删除节点

为了迭代,您需要维护自己的指向所查看元素的指针;这从
head
开始,然后跟随
next
指针,直到它到达末尾(即
next
为空):


您需要在代码中使用更多变量。
insert
操作修改两个节点。需要将上一个节点更改为指向新节点,并且需要创建新节点并使其指向上一个节点之后的节点(该节点可能为空,也可能不为空)

要遍历列表,请跟踪“当前节点”,可以从一个节点更改为下一个节点:

while (currentNode != 0) {
    do_something_with(currentNode);
    currentNode = currentNode->next;
}
当然,如果
do\u something\u with
删除了节点,那么之后就不能再向前移动了。此外,要从单链表中删除节点,需要在其前面有一个指向该节点的指针。因此,在这种情况下,您的循环可能会跟踪两个节点,当前节点和前一个节点,而不仅仅是一个节点。

您的问题在于:

void insert(node *previousNode, int num)
{
previousNode = new node;
previousNode->nodeNum = num;
previousNode->next = NULL;
}

insert(head, 20);
下面是这段代码的作用:
previousNode=新节点生成指向节点的指针,并将该指针指定给上一个节点。PreviousNode最初是一个复制头,现在它指向了一些新的东西。现在可以将值指定给新节点。换句话说,这个insert的实现并不是insert

你想做的事情更像:

void better_insert(node *previousNode, int num)
{
    node *post_node = new node;    #create a brand new pointer to a brand new node
    post_node->nodeNum = num;      #give it a number
    post_node->next = previousNode->next; #we want previousNode to be behind new node
    previousNode->next = post_node;     
}
它的作用是:在创建一个新节点并用一个新指针指向它之后,我们给它一个数字。下一件事是找出指针指向的位置

让我们假设我们在链表中波动一些节点。所有小写字母都是指针,好吗

a->next = b
现在假设我们希望node
x
位于
a
之后,并将数字10。。。我们称之为'better_insert(a,10)

post_节点
指向一个新节点(我们的节点x),并被分配10。酷

我们希望:

a->next = x
x->next = b
我们有:

a->next = b
x->next = null
a->next = b
x->next = null
函数的最后两行只是洗牌,直到符合要求为止

所以更详细地说

我们有:

a->next = b
x->next = null
a->next = b
x->next = null
因此,我们称之为:

post_node->next = previousNode->next; #we want previousNode to be behind new node
现在我们有: a->next=b x->next=b

现在我们呼吁:

previousNode->next = post_node;
我们最终会:

a->next = x
x->next = b
或者换句话说:

a->next = x
a->next->next = b

通常,链表的节点不包含其编号。它通常由一个数据和一个指向下一个节点的指针组成。你也应该让你的代码没有打字错误

typedef Data int;

struct node
{
   Data data; // some Data
   node *next;   // pointer to the next node
}
通常,您也不希望在指定的节点之后有一个新节点,而是希望有一个列表
void insert(node*previousNode,int-num)
signature建议在指定的前一个节点之后添加新节点

从技术上讲,可以通过三种方式将新节点添加到列表中。在列表的开头或结尾或中间的某个地方。添加到一开始是最快和最简单的

void insert(Data num)
{
    node* tmp = new node;  //make a new node
    tmp->data = num;       //fill in data
    tmp->next = head;      //set the next element of new one to be the current head
    head = tmp;            //set new element as the head
}
这样,您就可以在列表前面放置一个新元素。 始终从头到尾遍历单向链表

void print_all()
{
   node* current = head;      // start at head
   while(current != NULL){    // while element exists
     cout << current->data << ' ';   //print its data
     current = current->next; //move to the next one
   }
}

尝试实现这些功能。从我的经验来看,当你这样做时,它有助于组织你对数据结构和容器的思考,这是一种更为C++的方法来做这类事情。

< P>在你上面提到的列表中,你几乎没有什么信息。你应该把更多的信息放进去。例如,在值为nodeNum=10的节点上,您应该希望从该节点获取一些其他信息

node* search(node *head,int num){
      node *temp = head;//copy node reference into temp variable
      while (temp != NULL){
            if (temp->nodeNum == num){
               return temp;
            }
            temp = temp->next;
      }

} 
您可以使用node获取该节点中的数据

 res = search(head,10);
删除

bool delete(node *head,int num){
      node *temp = head;//copy node reference into template
      node *prev = NULL;
      bool isDelete = false;
      while (temp != NULL){
            if (temp->nodeNum == num){
               break;
            }else
               prev = temp;
               temp = temp->next;
            }
      }
      if (temp != NULL){
          prev-> next = temp->next;//maintain list
          delete temp;
          isDelete = true;
      }
      return  isDelete;
} 

为什么不拿一个示例代码来玩玩呢?这是理解数据结构的最好方法
 res = search(head,10);
bool delete(node *head,int num){
      node *temp = head;//copy node reference into template
      node *prev = NULL;
      bool isDelete = false;
      while (temp != NULL){
            if (temp->nodeNum == num){
               break;
            }else
               prev = temp;
               temp = temp->next;
            }
      }
      if (temp != NULL){
          prev-> next = temp->next;//maintain list
          delete temp;
          isDelete = true;
      }
      return  isDelete;
}