我写了下面的代码来删除一个双链表....开头和结尾的节点但是这些函数的执行在两者之间停止,程序被终止......
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,您需要以相同的方式更改所有的插入方法。
我不敢保证这是唯一的问题,但做出改变,你就会走上正确的道路。如果你有更多的问题,然后再次张贴,但记住张贴完整的代码。这是解决这类问题的唯一方法。
我对这段代码摘录有点困惑,但我假设这是整个摘录…
函数deletebeg
和deleteend
没有在类定义的任何地方声明,只在它之后声明。通常,它看起来像这样:
class List{
void aFunction(List * argument);
};
void List::aFunction(List * argument){
do something
};
但是撇开这些不讲,不要创建自己的链表,使用std::list<int>
(用你要创建链表的任何数据类型替换int)会更快,也会让你的生活更轻松。
这样做有很多原因,但最主要的原因是您不仅不必编写它,而且也不必调试它。例如,您创建的链表实现使用递归函数来删除自身(当函数调用自身时,它是递归的)。如果链表非常大,这可能会导致堆栈溢出,这是由于在函数中调用太多函数造成的。像这样的东西是追踪和发现的噩梦,并且会分散您对编程的真正的原因的注意力。这是假设原因不是建立链表。: P
虽然在c++中不经常看到在类之外声明函数,但这并非不可能。但这意味着head1是一个全局变量,在某处没有显示。
你忽略了实际调用deletebeg
和deleteend
的部分,所以很难确切地知道发生了什么。也许您正在使用已删除的指针。
我的猜测是,您使用一个节点调用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
。