【问题标题】:Using an array of pointers-to-pointers to manipulate the pointers it points to (C++)使用指向指针的数组来操作它指向的指针(C++)
【发布时间】:2017-11-06 21:55:10
【问题描述】:

我一直在自己做这个练习,以便在 C++ 上做得更好(搞乱我写的一个链表)。我想要做的是通过扭转指针来反转列表,而不是仅仅反向“打印”数据(这相对简单)。

我有一个指向指针的数组,每个指针指向链表中的一个节点。但这不是关于链表动力学(我理解)的问题,而是关于指针魔法的更多问题。

node 看起来像这样,

template<class T>
struct node {
    T data;
    node *next;

    node(T value) : data(value), next(nullptr) {}
};

还有有问题的代码,

  node<T> **reverseArr[listLength];
  node<T> *parser = root;

  for (auto i : reverseArr) {
      i = &parser;
      parser = parser->next;
  }   

  root = *(reverseArr[listLength - 1]);   
  for (int ppi = listLength - 1; ppi >= 0; --ppi) {
        if (ppi == 0) {
            (*reverseArr[ppi])->next = nullptr;
            //std::cout << "ppi is zero!" << "\t";
        }
        else {
            (*reverseArr[ppi])->next = (*reverseArr[ppi - 1]);
            //std::cout << "ppi, 'tis not zero!" << "\t";
        }
  }

我的逻辑:

  • 新的root 是列表的最后一个元素,
  • 反向遍历数组,
  • 通过将当前节点的nextNode 设置为循环中的下一个节点,将当前节点的next 指针设置为前一个。

发生了什么:

  • 如果我将调试打印语句保留为注释,则什么也没有。函数被调用,但链表保持不变(不反转)
  • 如果我取消注释调试打印,程序段错误(这对我来说没有多大意义,但似乎表明我的代码存在缺陷)

我怀疑我错过了什么,一双新的眼睛可能会抓住它。我是不是对数组处理不当(没有考虑到指针或其他东西的衰减)?

【问题讨论】:

  • 欢迎来到 Stack Overflow。请花时间阅读The Tour 并参考Help Center 中的材料,您可以在这里问什么以及如何问。
  • 调试器是解决此类问题的正确工具。 询问 Stack Overflow 之前,您应该逐行浏览您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 edit 您的问题包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
  • 感谢您的反馈。我会尽快编辑问题(以更好地反映指南)。

标签: c++ arrays pointers pointer-to-pointer


【解决方案1】:

你想多了这个问题。反转单链表的正确方法比你想象的要简单得多,而且根本不涉及数组。

您需要做的就是遍历列表,将每个节点的next 指针设置为列表的头部,然后将列表的头部设置为该节点。本质上,您正在取消每个节点的链接并将其插入到列表的开头。一旦你到达终点,你的名单就会颠倒过来。

这只是需要一点小心,因为你做事的顺序很重要。应该这样做:

template <class T>
node<T> * reverse( node<T> * head )
{
    node<T> *current = head;
    head = NULL;

    while( current != NULL )
    {
        // store remainder of list
        node<T> *remain = current->next;

        // re-link current node at the head
        current->next = head;
        head = current;

        // continue iterating remainder of list
        current = remain;
    }

    return head;
}

该操作具有线性时间复杂度。您可以通过传递列表的头节点来调用它,如下所示:

root = reverse( root );

不用说,用任何不是列表头的节点调用此函数或传入包含循环的列表都是一个坏主意。 p>

【讨论】:

  • 回到它,这很不幸,但我问的问题对于正确的答案来说太模糊了(我觉得修剪它/添加调试不会有太大改善)。在谈到链表以及如何反转它们的指针时,Paddy 的回答是正确的(我之前已经使用递归做过类似的事情)。我的初衷是故意尝试使用指针对指针及其关系来实现相同的目标(或者至少看看我能走多远)。接受这个答案好吗?我相信它回答了被问到的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-25
  • 2013-04-19
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多