【问题标题】:C++ Doubly linked list printingC++ 双向链表打印
【发布时间】:2016-01-05 01:00:54
【问题描述】:

我在使用双向链表课程时遇到了一些困难,这是我大学项目的一部分。类的代码是这样的:

class container
{
public:
    class node
    {
        public:
        node * prev;
        node * next;
        int value;
    };

container(int v);

node *start; // first element of the list
node *finish; // last element of the list
void insert_start(node *start, int val);
void print_container(); 
}

函数 insert_start 应该将元素添加到列表的开头。代码如下:

void container :: insert_start(node *start, int val)
{
    if(start!=NULL)
    {
        cout << "in insert_start" << endl;
        cout << "number added:" << val << endl;

        node *element = new node;

        element->value=val;
        element->next=start;
        start=element;
        start->prev=NULL;
    }
    else
    {
        cout << "List is empty" << endl;
    }
}

函数 print_container 应该打印我的链表。代码如下所示:

void container::print_container()
{
    node *tmp;
    tmp = start;
    while(tmp!=nullptr)
    {
        cout << tmp->value << endl;
        tmp=tmp->next;
    }
}

很遗憾,我的程序存在两个问题。首先,它 似乎在数据结构的添加元素中添加了相同的随机值。其次,在执行函数 print_container 期间存在分段错误。我想这可能是 insert_start 函数中的一个错误(或多个错误),但我对此并不完全确定。

这是测试程序:

int main(void)
{
    int how_many_pieces;

    container L(6);

    L.insert_finish(L.finish,3);
    cout << "added element: " << L.finish->value << endl;

    L.insert_start(L.start,8);
    cout << "added element: " << L.start->value << endl;

    L.insert_start(L.start,12);
    cout << "added element: " << L.start->value << endl;


   //show elements of the L list
   L.print_container();
   cout << "\n";

return 0;
}

感谢您的帮助。

【问题讨论】:

    标签: c++ doubly-linked-list


    【解决方案1】:

    首先,不要将节点作为参数传递——你不需要。容器类已经可以看到开始和结束节点,将它们传递进来只会让事情变得混乱。

    其次,您应该将这些设为私有,以便使用该类的任何人都必须使用您的 insert_start 或 insert_finish 函数。

    新类将如下所示:

    class container
    {
        private:
            class node
            {
                public:
                node * prev;
                node * next;
                int value;
            };
    
            node *start; // first element of the list
            node *finish; // last element of the list
    
        public:
            container(int v);
    
            void insert_start(int val);
            void print_container();
    };
    

    第三,确保为每个方向设置链接。例如,在您的 insert_start 函数中:

    node *element = new node;
    
    element->value = val;
    element->next = start;
    element->prev = NULL;
    start->prev = element; //This part was missing
    start = element;
    

    如果不将原始节点引用回新节点,您会将其视为普通的单链表。如果您想要双向链表提供的遍历灵活性,则需要正确设置链接。

    【讨论】:

      【解决方案2】:

      在这段代码中:

      void container :: insert_start(node *start, int val)
      {
          if(start!=NULL)
      

      最后一行应该引用哪个start?是检查参数值,还是公共类值?

      此外,如果列表为空,您可能还想做一些事情而不是打印消息。列表必须以某种方式开始。


      (附录)

      至少有两种方法可以防止此问题。我将同时显示三个:

      void container :: insert_start(node *node_to_insert, int val)
      {
          if (this->start != NULL)  // is list not empty?
      

      看起来几乎一样,对吧?

      • 现在形式参数名称表明了它的含义。顾名思义,指向的节点将被添加到列表中。
      • 对象实例值通过this 关键字访问。这在语法上消除了同名变量的范围,并真正帮助程序员轻松发现什么是什么。
      • 注释阐明了语句的高级意图,这使任何检查代码的人都可以轻松识别可能的差异。
      • 参数名称不再匹配对象成员名称。虽然名称相互平行通常很有用(p_x, p_y, p_z 用于初始化成员变量的三个参数值x, y, z),但为了简单和清晰,它们确实应该保持不同。

      【讨论】:

      • 公共类值。我希望 node *start 对类容器中的所有函数都是可见的,而不会出现访问该节点的复杂情况。可能有更好、更安全和更好的方法来做到这一点,但我在 C++ 方面还不是很先进,我想首先编写工作容器类。无论如何,谢谢你的帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 2022-01-15
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多