错误:Debug Assertion Failed!
今天花了好久才解决了本篇文章中的一个错误,代码bug当然是不可避免的,但是我们可以尽可能的优化他,减少他。
错误分析:主要原因是求解约瑟夫环的问题时,使用了我上一篇文章的循环单链表的模板类,但是我在实际求解中并没有用模板类中的Remove(删除)这个成员函数(不用是因为我定义的删除函数本身的局限性造成的),直接是
preNode = currNode;
currNode =currNode->link;
也就是直接把前后两个节点建立连接,再释放要删除的节点,那么问题来了,这个时候私有成员last(即始终指向循环单链表尾节点的指针)并没有得到更新,也就是说last指向的节点在早已经被delete(释放)了,在主函数main返回的时候,系统调用析构函数的时候会对last指向的节点再一次释放,图中错误就应运而生了!(这是我一个多小时的分析结果,如有不当,希望大牛指正!)。下面贴出错误处的代码:
好了,现在贴出整个约瑟夫问题的处理(包括循环单链表的模板类和主函数),约瑟夫环是循环单链表的一个重要应用,也是一个很实用的问题,希望大家都能够掌握,如有不当,万望指正、批评!
//模板类
//循环链表模板class
#include <iostream>
using namespace std;
template<class T>
struct CircleLinkNode {
T data;
CircleLinkNode<T> *link;
//构造函数
CircleLinkNode(CircleLinkNode<T> * next = NULL) : link(next) {}
CircleLinkNode(T d, CircleLinkNode<T> * next = NULL) : data(d), link(next) {}
};
template<class T>
class CircleList {
public:
CircleList(const T & x); //构造函数
CircleList(CircleList<T> & L); //复制构造函数
~CircleList(); //析构函数
int Length() const; //计算循环链表的长度
bool IsEmpty()
{
return first->link == first ? true : false; //判断是否是空表
}
CircleLinkNode<T> * getHead() const; //返回附加头节点的地址
void setHead(CircleLinkNode<T> * p); //设置附加头节点的地址
CircleLinkNode<T> * Search(T x); //搜索含数据x的节点
CircleLinkNode<T> * Locate(int i); //搜索第i个元素的地址
T getData(int i); //取出第i个元素的值
void setData(int i, T & x);