双链表及其删除

double linked list and its deletion

本文关键字:删除 链表      更新时间:2023-10-16

我写了下面的代码来删除一个双链表....开头和结尾的节点但是这些函数的执行在两者之间停止,程序被终止......

struct nodeb
{
    int value;
    nodeb *next;
    nodeb *pre;   //pre of first node and next of last node point to null...
    nodeb(int a,nodeb *ptr1=0, nodeb *ptr2=0):value(a), next(ptr1), pre(ptr2)
    {}
};
class doublelist
{
private:
nodeb *head1,*head2;
public:
doublelist():head1(0),head2(0)
  {cout<<"double list created"<<endl;}

void deletebeg()//delete beginning node
{
    if(head1->next==0)
    {
        nodeb *ptr=head1;
        head1=head2=0;
        delete ptr;
    }
    else 
    {
        nodeb *ptr=head1->next;
        nodeb *ptr1=head1;
        ptr->pre=0;
        head1=ptr;
        delete ptr1;
    }
}

void deleteend()//delete end node
{
    nodeb *ptr=head1;
    nodeb *ptr1;
    while(ptr->next!=0)
    {
        ptr1=ptr;
        ptr=ptr->next;
    } 
    delete ptr;
    ptr1->next=0;
}
};  //class ends here

int main()
{
    doublelist list1;
nodeb node(8);
nodeb node1(7);
nodeb node2(9);
nodeb node3(4);
list1.insertbeg(node);
list1.insertbeg(node1);
    list1.insertafter(node3,1);
list1.insertend(node2);  //insertbeg,insertafter and insertend are three functions i defined to        attach nodes at the beginning,at a particular location and at  the end of the list 
list1.deletebeg();
} 
谁能告诉我是什么问题?这是用于插入
的三个函数的链接

现在我可以看到所有的代码,问题很简单。你的deletebeg函数删除了带有delete的开始节点,但是你没有分配带有new的节点。如果您使用new创建内存,则应该只使用delete内存。

通常,当人们编写链表类时,他们使用new在列表方法中分配节点。然后他们可以安全地delete方法中的节点。您正在执行删除操作,但没有使用new。所以你需要重写你的主函数,像这样

int main()
{
    doublelist list1;
    list1.insertbeg(8); // add 8 to beginning of list
    list1.insertbeg(7); // add 7 to beginning of list
    list1.insertafter(4,1); // add 4 after first item of list
    list1.insertend(9); // add 9 to end of list
    list1.deletebeg();
} 

然后你需要像这样重写你的方法

void insertbeg(int value)//insert beginning
{
    nodeb* a = new nodeb(value); // allocate node inside of method using new
    if(head1==0)
    {
        head1=a;
        head2=a;
        a->next=0;
        a->pre=0;
    }
    else
    {
        nodeb *ptr=head1;
        ptr->pre=a;
        a->pre=0;
        a->next=ptr;
        head1=a;
    }
}

我只展示了insertbeg,您需要以相同的方式更改所有的插入方法。

我不敢保证这是唯一的问题,但做出改变,你就会走上正确的道路。如果你有更多的问题,然后再次张贴,但记住张贴完整的代码。这是解决这类问题的唯一方法。

我对这段代码摘录有点困惑,但我假设这是整个摘录…

函数deletebegdeleteend没有在类定义的任何地方声明,只在它之后声明。通常,它看起来像这样:

class List{
    void aFunction(List * argument);
};  
void List::aFunction(List * argument){
    do something
};

但是撇开这些不讲,不要创建自己的链表,使用std::list<int>(用你要创建链表的任何数据类型替换int)会更快,也会让你的生活更轻松。

这样做有很多原因,但最主要的原因是您不仅不必编写它,而且也不必调试它。例如,您创建的链表实现使用递归函数来删除自身(当函数调用自身时,它是递归的)。如果链表非常大,这可能会导致堆栈溢出,这是由于在函数中调用太多函数造成的。像这样的东西是追踪和发现的噩梦,并且会分散您对编程的真正的原因的注意力。这是假设原因不是建立链表。: P

虽然在c++中不经常看到在类之外声明函数,但这并非不可能。但这意味着head1是一个全局变量,在某处没有显示。

你忽略了实际调用deletebegdeleteend的部分,所以很难确切地知道发生了什么。也许您正在使用已删除的指针。

此外,虽然NULL通常是零,但不能保证编译器的情况是这样的。你应该使用NULL而不是0。

我的猜测是,您使用一个节点调用deleteend,该节点出于某种原因具有head1==0,然后ptr1从未初始化,并且当您试图解引用未初始化的指针时,程序在deleteend的最后一行崩溃。

关于我之前的回答的进一步评论

这个代码是错误的

void insertbeg(int value)//insert beginning
{
    nodeb a(value); // create node on the stack
    if(head1==0)
    {
        head1=&a;
        head2=&a;
        a.next=0;
        a.pre=0;
    }
    else
    {
        nodeb *ptr=head1;
        ptr->pre=&a;
        a.pre=0;
        a.next=ptr;
        head1=&a;
    }
}

上面的代码会有你描述的问题,当你说"head1和head2将指向任何地方"。但是这段代码是完全不同的

void insertbeg(int value)//insert beginning
{
    nodeb* a = new nodeb(value); // allocate node inside of method using new
    if(head1==0)
    {
        head1=a;
        head2=a;
        a->next=0;
        a->pre=0;
    }
    else
    {
        nodeb *ptr=head1;
        ptr->pre=a;
        a->pre=0;
        a->next=ptr;
        head1=a;
    }
}

它的不同之处在于它使用new来创建对象。当您使用new时,对象在退出函数时不会被销毁。这就是new的意思。但是,当您使用new时,您还必须在完成节点后使用delete