【问题标题】:Implementing a double linked list in C++, pointers and odd values用C++实现双链表,指针和奇数值
【发布时间】:2014-01-21 19:16:38
【问题描述】:

我在 C++ 中相当生疏,我正在尝试实现一个双链表,但我遇到了一些读取违规并给出了一些奇怪的值。

    #include <iostream>

struct Node
    {
      int val;
      Node* next;
      Node* prev;
};

class linkedList
{
  public:
    linkedList(); //constructor
    ~linkedList(); //destructor
    void push_back(int x);
    void addtofront(int x);
    //void deleteNode(int x);
    bool isempty();
    void firstelem();
    void prnt_tail();
    /*void insert_after(int x, int y);
    void insert_before(int x, int y);*/
  private:
    
    Node* head;
    Node* next;
    Node* prev;


};


linkedList::linkedList(){};


linkedList::~linkedList(){};


void linkedList::push_back(int x)
{
    linkedList* list = this;
    Node temp;
    temp.val=x;
    temp.next=NULL;
    temp.prev=NULL;
    if (!head)
  {
    linkedList* list = new linkedList();
    list->head;
    head = new Node;
    head->val = x;
    head->next = NULL;
    head->prev = NULL;
  }
  else
  {
    Node* temp1;
    temp1=head;
    while (temp1->next!=NULL)
    {
        temp1 = temp1->next;
    }

    temp.next= NULL; 
    temp.prev=temp1;
    temp.val = x;

  }
};

void linkedList::addtofront(int x)
{
    linkedList* list = this;
    Node temp;
    temp.val=x;
    temp.next=NULL;
    temp.prev=NULL;
    if (!head)
  {
    linkedList* list = new linkedList();
    list->head;
    head = new Node;
    head->val = x;
    head->next = NULL;
    head->prev = NULL;
  }
    else
    {
        list->head->prev=&temp;
        temp.next=head;
        head=&temp;
    }
};

//void linkedList::deleteNode(int x)
//{
//  if(head)
//  {
//      linkedList *ptr = head;
//      while(ptr->node.val != x)
//      {
//          ptr = ptr->node.next;
//      }
//      (ptr->node.next)->prev=ptr->node.prev;
//      ptr->node.prev=ptr->node.next;
//      delete ptr;
//  }
//  else
//      std::cout<<"empty list";
//}


bool linkedList::isempty()
{
    if(head)
        return false;
    else return true;
};


void linkedList::firstelem()
{
    std::cout<<head->val;
};


void linkedList::prnt_tail()
{
    if(head)
    {
        Node *temp;
        temp=head;
        temp=head->next;
        std::cout<<temp;
        while(temp->next!=NULL)
        {
            std::cout<<temp->val<<" ";
        }
        std::cout<<temp->val;
    }
    else
    {
        std::cout<<"empty list";
    }
    
};


//linkedList::insert_after(int x, int y)
//{
//
//}
//
//linkedList::insert_before(int x, int y)
//{
//
//}

和我的主要

#include "linkedlist2.h"
#include <stdlib.h>
#include <iostream>



int main()
{
    linkedList example;
    if(example.isempty())
        std::cout<<"this list is empty "<<"\n";
    else
        std::cout<<"this list is not empty"<<"\n";
    for (int i = 1; i<=20; i++)
    {
        example.push_back(i);
        //example.prnt_tail();
    }
    example.addtofront(25);
    example.firstelem();
    std::cout<<"\n";
    example.addtofront(28);
    example.firstelem();
    std::cout<<"\n";
    if(example.isempty())
        std::cout<<"this list is empty "<<"\n";
    else
        std::cout<<"this list is not empty"<<"\n";
    
    //example.push_back(26);
    //std::cout<<example.head->next->val;
    example.firstelem();
    std::cout<<"\n";
    example.prnt_tail();
    std::cout<<"\n";
    system("pause");
}

当我运行 main 我得到

此列表为空

-858993460

-858993460

此列表不为空

-858993460

CCCCCCCC

我也得到了错误

访问冲突读取位置0xCCCCCCD0。

接下来要执行的语句是“void linkedList::prnt_tail()”中的while循环

我很确定我的问题在于我的指针等等。就像我说的那样,我真的很生疏,所以如果你能提供任何帮助,我们将不胜感激,即使是在与我的问题没有直接关系的事情上。

【问题讨论】:

  • 不要重新发明轮子。使用std::list;如果您想学习,请使用调试器了解指针的值。
  • @BasileStarynkevitch 不能做一个练习来提高他们的技能吗?
  • addToFront 中有 2 个奇怪的东西。第一个是您正在创建linkedList 的新实例,而您可以执行this-&gt;head = head。第二个是你在函数之外使用temp,但它的作用域是函数addToFront
  • 你甚至没有初始化成员。完成此操作后,手动单步执行代码。不要使用调试器,而是在编写之前三思而后行。 (那里有足够的问题可以写一篇文章。)
  • 0xCCCCCCD0 看起来您正在使用未初始化的内存。 stackoverflow.com/questions/370195/…

标签: c++ pointers linked-list


【解决方案1】:

所以,这段代码有很多问题。让我们看看我们能做些什么:

  1. 奇怪的是,node 对象和 linkedList 对象中都有 nextprev 成员。让我们通过使linkedList 对象指向第一个节点(即头节点)来解决此问题,然后使用每个节点中的成员指向下一个对象。

    这意味着我们有:

    struct Node {
        int val;
        struct Node* next;
        struct Node* prev;
    };
    
    class linkedList {
        public:
            linkedList(); //constructor
            ~linkedList(); //destructor
    
            void push_back(int x);
            void addtofront(int x);
            bool isempty();
    
        private:
            Node* head;
    };
    
  2. 让我们修复 push_back 中的一些错误。首先,无论linkedList的状态是什么,我们都需要在堆上创建一个新的Node,然后我们将把Node放在linkedList的某个位置。

    void linkedList::push_back(int x)
    {
        Node *node = new Node;
        node->next = NULL;
        node->prev = NULL;
        node->val = x;
    
        if (head == NULL) {
            head = node;
        } else {
            Node *last = head;
            while (last->next != NULL)
                last = last->next;
            last->next = node;
            node->prev = last;
        }
    }
    
  3. 我们还需要修复push_front。这段代码看起来应该有点类似于push_back

    void linkedList::addtofront(int x)
    {
        Node *node = new Node;
        node->next = NULL;
        node->prev = NULL;
        node->val = x;
    
        if (head == NULL) {
            head = node;
        } else {
            node->next = head;
            head->prev = node;
            head = node;
        }
    }
    
  4. 如果你要编写一个构造函数,你可能应该正确地这样做:

    linkedList() {
        head = NULL;
    }
    
  5. 还值得注意的是,您需要一个真正的析构函数来清理您在堆上创建的所有这些对象。然后你还需要实现copy constructor and assignment operator

【讨论】:

  • 感谢您的帮助。
【解决方案2】:

除了一个多余的无用分号,这看起来是错误的:

linkedList::linkedList(){};

构造函数应该为成员提供初始值,而您还没有这样做。让指针成员未初始化是非常糟糕的风格,并且是许多问题的原因。

因为这些成员没有被初始化,所以当您稍后从它们中读取时(例如 isEmpty() 的测试 if (head)),它将是未定义的行为。

【讨论】:

    【解决方案3】:

    首先,在addToFrontpush_back 中,您可能不想在堆上创建新的链表。您已经有一个要修改的链表(当前正在运行该方法的链表)。不要在这里创建新的链表。

    但是,您确实希望在堆上创建新节点,而不是在堆栈上。至少在一个地方,您在堆栈上创建一个节点,例如

    Node temp;
    

    然后存储并使用指向该对象的指针。一旦函数退出,那个变量就消失了,那个指针指向垃圾。

    【讨论】:

      【解决方案4】:

      在链表类中,(Node* next;) 和(Node* prev;) 是extra

      【讨论】:

        猜你喜欢
        • 2013-10-29
        • 2012-04-20
        • 2015-09-09
        • 1970-01-01
        • 2013-04-28
        • 1970-01-01
        • 2023-04-07
        • 2020-05-25
        • 1970-01-01
        相关资源
        最近更新 更多