用C ++,指针和奇数值实现双链表

时间:2014-01-21 19:16:39

标签: c++ pointers linked-list

我在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");
}

当我运行主要时我得到

  

此列表为空

     

-858993460

     

-858993460

     

此列表不为空

     

-858993460

     

CCCCCCCC

我也得到了错误

  

访问冲突读取位置0xCCCCCCD0。

并且要执行的下一个语句是“void linkedList :: prnt_tail()”中的while循环

我很确定我的问题出在我的指针中。就像我说的那样,我真的很生疏,所以你能给予的任何帮助都会受到高度赞赏,即使是与我的问题没有直接关系的事情。

4 个答案:

答案 0 :(得分:3)

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

  1. 您的next个对象和prev个对象中都有nodelinkedList个成员,这很奇怪。让我们通过使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

答案 1 :(得分:1)

除了额外无用的分号外,这看起来不对:

linkedList::linkedList(){};

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

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

答案 2 :(得分:0)

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

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

Node temp;

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

答案 3 :(得分:-1)

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