【问题标题】:Assigning doubly linked-list pointers in constructor在构造函数中分配双向链表指针
【发布时间】:2013-04-23 21:25:32
【问题描述】:

我正在尝试为双向链表创建一些节点并将它们打印出来。所以我创建了我的 dnode 类:

template <typename T>
class dnode
{
    public:
        T nodeValue;
        dnode<T> *prev;
        dnode<T> *next;

        dnode() : prev(this), next(this) {}

        dnode(const T& item, dnode<T> *prevNode = NULL, dnode<T> *nextNode = NULL) :
            nodeValue(item), prev(prevNode), next(nextNode) {}

};

然后我有我的 writeList 函数:

template <typename T>
void writeDLinkedList(dnode<T>* header, const string& seperator = " ")
{
    dnode<T> *p = header->next;

    while (p != header)
    {
        cout << p->nodeValue << seperator;
        p = p->next;
    }

    cout << endl << endl;
}

在main中,我创建了一个头指针和两个节点,使用构造函数来分配循环列表中的前一个和下一个节点:

dnode<int> *header, *one, *two;

header = new dnode<int>(0, two, one);
one = new dnode<int> (10, header, two);
two = new dnode<int> (25, one, header);

writeDLinkedList(header);

当我调用 writeDLinkedList 时,我遇到了分段错误。我对此感到困惑,所以我最终尝试单独输出每个节点值以查看指针是否正常工作。事实证明他们不是。相反,我必须这样做才能使打印功能正常工作:

header = new dnode<int>;

one = new dnode<int> (10);
two = new dnode<int> (25);
header->next = one;
one->next = two;
two->next = header;

writeDLinkedList(header);

我想知道为什么我的构造函数没有按应有的方式工作。是初始化列表吗?

【问题讨论】:

  • prevnext 应初始化为 NULL,而不是 this。然后应更新对有效节点的检查以在循环时查找NULL

标签: c++ list pointers constructor


【解决方案1】:

您的构造函数正在工作。问题是您在给变量赋值之前就在使用它们。

dnode<int> *header, *one, *two; 
// one and two have undefined values at this point

header = new dnode<int>(0, two, one);
// so undefined values get put into header->next and header->prev

在双向链表中有指针循环,节点 A 指向节点 B,节点 B 又指向节点 A。根据定义,指针循环不能仅在构造函数中创建。因为必须首先创建节点A或节点B。首先创建的哪个节点不能指向另一个节点,因为那个节点还不存在。

双向链表比你想象的要复杂一些。

【讨论】:

  • 是的,我想我低估了他们。感谢您的简洁回答。
【解决方案2】:

您没有正确管理节点。试试这个:

template <typename T>
class dnode
{
    public:
        T nodeValue;
        dnode<T> *prev;
        dnode<T> *next;

        dnode() : prev(NULL), next(NULL) {}

        dnode(const T& item, dnode<T> *prevNode = NULL) :
            nodeValue(item), prev(prevNode), next(NULL)
        {
            if (prev)
            {
                if (prev->next)
                    prev->next->prev = this;
                prev->next = this;
            }
        }

        ~dnode()
        {
            if (prev)
                prev->next = next;

            if (next)
                next->prev = prev;
        }
};

.

template <typename T>
void writeDLinkedList(dnode<T>* header, const string& seperator = " ")
{
    dnode<T> *p = header;

    while (p != NULL)
    {
        cout << p->nodeValue << seperator;
        p = p->next;
    }

    cout << endl << endl;
}

.

dnode<int> *header, *one, *two;

header = new dnode<int>(0);
one = new dnode<int> (10, header);
two = new dnode<int> (25, one);

writeDLinkedList(header);

【讨论】:

    【解决方案3】:

    我认为您正在尝试创建双重循环列表。您可以先创建单个节点,然后再连接它们。在连接两个节点后的双循环列表中,您必须将最后一个节点连接到第一个节点才能闭合圆圈。 您可能想尝试类似的东西。我已经为 int 做了,但它可以很容易地放入模板中。

    #include<iostream>
    
    class dnode
    {
    
    public:
    
        dnode(int a):prev(this), next(this), nodeValue(a)
         {}
        void connectNode(dnode *newNode)
         {
            if(newNode != NULL)
            {
                dnode*head = this->next;
                this->next = newNode;
                newNode->prev = this;
                newNode->next = head;
                head->prev = newNode;
            }
         }
    
        void writeDNode()
         {
         dnode *p = this->next;
            while(p != this)
             {
                std::cout<<"Element "<<p->nodeValue<<std::endl;
                p = p->next;
             }
         }
    private:
        int nodeValue;
        dnode *prev;
        dnode *next;
    
     };
    
    
    int main(int argc, char*argv[])
     {
        dnode* header = new dnode(-1);
        dnode *one = new dnode(23);
        dnode *two = new dnode(45);
        dnode *three = new dnode(67);
        header->connectNode(one);
        one->connectNode(two);
        two->connectNode(three);
        header->writeDNode();
        std::getchar();
    
    
    
     }
    

    【讨论】:

      猜你喜欢
      • 2020-06-15
      • 1970-01-01
      • 2021-07-20
      • 2017-07-20
      • 1970-01-01
      • 2011-06-03
      • 2021-07-19
      • 2013-11-15
      • 1970-01-01
      相关资源
      最近更新 更多