C ++链接列表遍历和修改

时间:2017-10-16 08:51:32

标签: c++ pointers linked-list singly-linked-list

链接列表:

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 = pointer2 - 指针指向2指向的指针?
  • 指针 - > next = pointer2 - 指针指向指向指针2链接节点的链接节点
  • 指针 - > next = pointer2-> next - 指针指向指针指向的链接节点后指向的链接节点
  • pointer = pointer2-> next - 在指针指向一个指针后,指针指向链接节点。

是吗?

3 个答案:

答案 0 :(得分:1)

  

节点可以指向自己吗?

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

例如,您可能决定当节点指向自身时,则表示链接列表的结尾。然后,您可以在此处编写一个函数,该函数在整数链表中搜索数字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。它是&#39; s也不可能传入一个空列表。这两个问题都在nullptr示例中得到修复,但实际上即使使用&#34; node == node->next也可以修复它们。 list&#34; rule。关键是在链表的末尾添加一个虚拟节点,并要求这个额外的节点具有这个属性。你不需要检查这个节点是否有三个属性,等等一个节点本身代表一个空列表。)

答案 1 :(得分:0)

你最后指向最后一个指针:

...
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 ++,它会更清楚。

答案 2 :(得分:0)

Linked data structure有一个指针用于当前数据,一个用于下一个指针(指向下一个当前数据的指针),如果是双向链表,则指向前一个指针(指向前一个的当前数据。)

  

节点可以指向自己吗?喜欢指针 - &gt;下一个=指针 - &gt;下一个

是。这与为自己分配任何指针相同。不是很有用。

  
      
  • 指针 - &gt; next = pointer2-&gt; next - 指针指向指针指向的链接节点后指向的链接节点
  •   
  • pointer = pointer2-&gt; next - 在指针指向一个指针后,指针指向链接节点。
  •   

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