C++链表遍历和修改

C++ Linked List traversal and modification

本文关键字:修改 遍历 链表 C++      更新时间:2023-10-16

链表:

pointer2 -> [a]
pointer ->[a] -> [b] -> [c] -> [d] -> null    
pointer = b; //makes it point one down so it will be pointer -> [b] ->[c] -> [d] -> null    
pointer = pointer 2; //makes pointer point back to where it was pointing to before, both pointers point to [a]   
pointer2 = pointer->next; //makes pointer 2 point to [b]
pointer2->next = pointer->next; //makes [c] point to [b]

我的理解正确吗?节点可以指向自己吗?类似pointer->next=pointer->next

基本上:

  • pointer=pointer2-使指针指向指针2所指向的对象
  • pointer->next=pointer2-使指针指向的链接节点指向pointer2链接节点
  • pointer->next=pointer2->next-使指针指向的链接节点指向指针2指向的链接后的一个链接节点
  • pointer=pointer2->next-使指针指向一个pointer2所指向的链接节点

是这样吗?

节点可以指向自己吗?

正如其他人所说,这当然是可能的。但也许你的意思是"它有效吗?"。答案是,这取决于操纵链表的代码。如果您正在编写该代码,那么它是否有效取决于您

例如,您可能会决定,当一个节点指向自己时,这表示链表的末尾。下面是如何编码一个函数,该函数在整数链表中搜索数字3:

struct ListNode {
int value;
ListNode* next;
};
bool containsThree(ListNode* list) {
for (; list->next != list; list = list->next) {
if (list->value == 3) {
return true;
}
}
// Also check final node
if (list->value == 3) {
return true;
}
return false;
}

或者,您可以决定next == nullptr意味着列表的末尾。在这种情况下,containsThree看起来更像这样:

bool containsThree(ListNode* list) {
for (ListNode* node = list; node; node = node->next) {
if (node->value == 3) {
return true;
}
}
return false;
}

有了这个新函数,如果任何节点指向自己,那么函数将永远循环。你可以修复这个问题,甚至可以在列表中检查更大的循环,比如:

bool containsThree(ListNode* list) {
std::set<ListNode*> seenNodes;
for (ListNode* node = list; node; node = node->next) {
if (seenNodes.count(node)) {
break;
}
seenNodes.insert(node);
if (node->value == 3) {
return true;
}
}
return false;
}

这个最后的函数有一个问题:它比前一个函数有很大的性能损失。因此,是否允许列表中的循环取决于您,您将在函数中检查它们,还是不允许循环。任何一个都是正确的,你只需要做出决定并坚持下去

(编辑:第一个示例函数有点混乱,因为结束循环的条件在最后一个节点中查找3之前。也不可能传入空列表。这两个问题在nullptr示例中都得到了解决,但实际上即使使用"node == node->next表示列表结束"也可以解决它们规则关键是在链表的末尾添加一个虚拟节点,并要求这个额外的节点具有此属性。你不需要检查这个节点的三个ness,这样的节点本身就代表一个空列表。)

您是最后一个指针分配的正确执行者:

...
pointer2 = pointer->next; //makes pointer 2 point to [b]: Ok
pointer2->next = pointer->next; //makes [c] point to [b]: Wrong

pointer2指向[b],pointer->next指向b。最后一个指针赋值使b指向自身,导致:

pointer2 -> b -> b !

和:

pointer -> a -> b -> b

您的误解可能来自这样一个事实,即您的伪代码没有明确说明什么是a、b、c和d,什么代表下一个,以及您在哪里使用地址。用C++编写所有这些内容,会更加清晰。

链接的数据结构有一个指针用于当前数据,一个用于下一个(指向下一个的当前数据的指针),如果是双链表,则有一个指向上一个(即指向上一个中当前数据的指标)。

节点可以指向自己吗?类似pointer->next=pointer->next

是。这和将任何指针分配给它自己是一样的。不是很有用。

  • pointer->next=pointer2->next-使指针指向的链接节点指向指针2指向的链接后的一个链接节点
  • pointer=pointer2->next-使指针指向一个pointer2所指向的链接节点

然而,在此之后,当前数据指针和下一个数据指针是相同的,并且指向相同的东西。这意味着,如果有人想沿着这个链表遍历,如果没有指针检查,他们可能会陷入无限循环。