【问题标题】:C++ Linked List traversal and modificationC++链表遍历和修改
【发布时间】:2018-03-27 17:47:19
【问题描述】:

链表:

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指向的一个链接节点之后的一个。

对吗?

【问题讨论】:

  • 在普通 PC 上,指针变量只是一个整数,其值是内存中的地址。您可以按照自己喜欢的方式分配此值,就像任何其他变量一样。当然,只要变量的类型是兼容的。
  • 是的,我明白指针是什么。我试图确认我对如何导航链接列表的理解是否正确。就像底部的那些作业做我认为他们做的那样。

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


【解决方案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;
}

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

(编辑:第一个示例函数有点混乱,因为结束循环的条件只是 before 我们在最终节点中查找3。也无法传入空列表。这两个问题在nullptr 示例中都已修复,但实际上即使使用“node == node-&gt;next 表示列表末尾”规则也可以修复它们。关键是在末尾添加一个虚拟节点链表,并要求这个额外的节点有这个属性。你不需要检查这个节点的三性,这样一个节点本身就代表一个空列表。)

【讨论】:

    【解决方案2】:

    最后一个指针赋值是正确的:

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

    pointer2 指向 [b],pointer-&gt;next 指向 b。最后的指针赋值使 b 指向自身导致:

    pointer2 -> b -> b !
    

    和:

    pointer -> a -> b -> b
    

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

    【讨论】:

      【解决方案3】:

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

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

      是的。这与将任何指针分配给自身相同。不是很有用。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-29
        • 1970-01-01
        • 2013-07-28
        • 2018-11-23
        • 1970-01-01
        • 2019-02-24
        • 1970-01-01
        • 2019-11-08
        相关资源
        最近更新 更多