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
现在假设我们希望nodex
位于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;
}