努力学习的阿信 2021-05-23 20:03 采纳率: 90%
浏览 64
已结题

实现循环双向链表时,输出函数DispList出现错误

#include<iostream>					//循环双向链表
#include "LDLinkList.h"
#include "LDLinkList.cpp"

template<class Type>
class LinkNode {				//节点类
public:
	Type data;					//数据域,存放数据
	LinkNode<Type>* prior;		//指针域,指向前一个节点
	LinkNode<Type>* next;		//指针域,指向后一个节点
};

template<class Type>
class LinkList {			//链表类
private:
	int length;
public:
	LinkList();
	void InitList(LinkNode<Type>*& L);									//建立头节点
	void CreateList(LinkNode<Type>*& L, Type arr[], int& len);			//头插法建立循环单链表
	bool ListEmpty(LinkNode<Type>*& L);									//判断循环单链表是否为空
	int ListLength(LinkNode<Type>*& L);									//获取循环单链表长度
	void DispList(LinkNode<Type>*& L) const;							//输出循环单链表
	bool GetElem(LinkNode<Type>*& L, int& locate, Type& e);				//按照输入的数值查找循环单链表
	bool LocateList(LinkNode<Type>*& L, Type& e, int& locate);			//按照输入的元素值查找循环单链表
	bool InsertList(LinkNode<Type>*& L, int& locate, Type& e);			//将指定元素插入到执行位置
	bool DeleteList(LinkNode<Type>*& L, int& locate, Type& e);			//删除指定位置的元素并使用e接收要删除的元素值
	void DestoryList(LinkNode<Type>*& L) const;							//销毁循环单链表
	~LinkList();
};


template<class Type>
LinkList<Type>::LinkList()
{
	length = 0;				//初始值设置为零
	std::cout << "构造函数建立循环单链表对象完成!" << std::endl;
}
template<class Type>
void LinkList<Type>::InitList(LinkNode<Type>*& L)
{
	L = new LinkNode<Type>;
	L->prior = L;			//将节点L的指针prior,next指向自身
	L->next = L;
	std::cout << "InitList建立头节点完成!" << std::endl;
}
template<class Type>
void LinkList<Type>::CreateList(LinkNode<Type>*& L, Type arr[], int& len)
{
	LinkNode<Type>* pre;
	int i;
	length = len;							//获取双链表的长度
	for (i = 0;i < len;i++) {
		pre = new LinkNode<Type>;				//动态申请节点的存储空间
		pre->data = arr[i];
		pre->next = L->next;					//将节点s插入到循环单链表上
		L->next->prior = pre;
		pre->prior = L;
		L->next = pre;
	}
	std::cout << "CreateList建立循环双链表完成!" << std::endl;
}
template<class Type>
bool LinkList<Type>::ListEmpty(LinkNode<Type>*& L)
{
	//返回值true说明节点L的next指针指向节点L本身,因此链表为空,否则非空
	return (L->next == L);
}
template<class Type>
int LinkList<Type>::ListLength(LinkNode<Type>*& L)
{
	return length;
}
template<class Type>
void LinkList<Type>::DispList(LinkNode<Type>*& L) const
{
	LinkNode<Type>* pre = L;
	if (L->next == L)						//这是判断单链表是否还有其它节点
		std::cout << "DispList检测到单链表此时只有一个头节点,无法输出!" << std::endl;
	else {
		while (pre->next != L)					//找到最先插入的点
			pre = pre->next;
		while (pre != L) {
			std::cout << pre->data << " ";
			pre = pre->prior;					//将指针pre迁移一位指向上一个节点
		}
		std::cout << "\n";//换行并清空缓冲区的内容
		std::cout << "DispList输出循环链表完成!" << std::endl;
	}
}
template<class Type>
bool LinkList<Type>::GetElem(LinkNode<Type>*& L, int& locate, Type& e)
{
	LinkNode<Type>* pre = L;
	int i = 0;
	if (locate <= 0) {
		std::cout << "GetELem检测到违法输入!" << std::endl;
		return false;
	}
	while (i <= length - locate) {//将逻辑位置转换为单链表中的位置
		i++;
		pre = pre->next;
	}
	if (length - locate < 0) {//未查询到节点pre,查询越界(pre->next==L)
		std::cout << "GetElem未查询到结果(越界)!" << std::endl;
		return false;
	}
	else //此时在链表中查询到该节点pre(i>length-locate)
	{
		e = pre->data;								//使用元素e接收查询的值
		std::cout << "GetElem查询成功!" << std::endl;
		return true;
	}
}
template<class Type>
bool LinkList<Type>::LocateList(LinkNode<Type>*& L, Type& e, int& locate)
{
	LinkNode<Type>* pre = L;
	int i = 0;
	while (pre->data != e && pre->next != L) {//该节点的data数据域存放的不是e,该节点不是最后一个节点
		i++;
		pre = pre->next;
	}
	if (pre->next == L) {//已经查询到最后一个节点
		std::cout << "LocateList查询链表失败!(越界)" << std::endl;
		return false;
	}
	else				//说明在链表中查询到元素e
	{
		locate = length - i + 1;//元素的逻辑位置和在链表中的真实位置满足:逻辑位置+链表存储位置 = length+1
		std::cout << "LocateList查询链表成功!" << std::endl;
		return true;
	}
}
template<class Type>
bool LinkList<Type>::InsertList(LinkNode<Type>*& L, int& locate, Type& e)//将元素e插入到指定位置
{
	LinkNode<Type>* pre = L, * s;
	int i = 0;
	if (locate <= 0 || length - locate < 0) {
		std::cout << "InsertList检测到违法输入!" << std::endl;
		return false;			//返回函数调用点
	}
	while (i <= length - locate) {//逻辑位置转换成链表中的实际位置,判断是否越界
		i++;
		pre = pre->next;
	}
	s = new LinkNode<Type>;	//动态申请存储空间
	s->data = e;
	s->next = pre->next;	//节点s插入到单链表中,需要修改四个指针
	if(pre->next!=L)		//判断节点L是否存在下一个节点
		pre->next->prior = s;
	pre->next = s;
	s->prior = pre;
	length++;				//插入成功后更新循环链表长度
	std::cout << "InsertList插入节点成功!" << std::endl;
	return true;
}
template<class Type>
bool LinkList<Type>::DeleteList(LinkNode<Type>*& L, int& locate, Type& e)
{
	LinkNode<Type>* pre = L;
	int i = 0;
	if (locate <= 0) {
		std::cout << "DeleteList检测到违法输入!" << std::endl;
		return false;			//返回函数调用点
	}
	while (i < length - locate) {//逻辑位置转换成链表中的实际位置,判断是否越界
		i++;
		pre = pre->next;
	}
	if (length - locate < 0) {//若此时输入的locate小于链表长度,说明链表发生越界,删除失败
		std::cout << "DeleteList插入失败(越界)!" << std::endl;
		return false;
	}
	else//说明已经找到要删除的节点
	{
		pre->prior->next = pre->next;//删除这个节点
		pre->next->prior = pre->prior;
		e = pre->data;
		delete pre;
		length--;//删除后更新循环链表的长度
		std::cout << "DeleteList删除节点成功!" << std::endl;
		return true;
	}
}
template<class Type>
void LinkList<Type>::DestoryList(LinkNode<Type>*& L) const
{
	LinkNode<Type>* pre = L->next;
	while (L->next != L) {				//判断节点L的下一个节点是否为L
		L->next = pre->next;			//L的next指针指向要删除的节点的下一个节点
		delete pre;						//删除节点并将指针pre重置指向节点L的下一个节点
		pre = L->next;
	}
	delete L;
	std::cout << "DestoryList销毁链表成功!" << std::endl;
}
template<class Type>
LinkList<Type>::~LinkList<Type>()
{
	std::cout << "析构函数释放循环单链表对象!" << std::endl;
}


int main() {
	using std::cout;
	using std::endl;
	LinkNode<int>* L;
	LinkList<int> obj;
	int arr[]{ 1,2,3,4,5,7,8,9,10 };
	int len = sizeof(arr) / sizeof(arr[0]);//获取数组的长度
	int length = 0;

	obj.InitList(L);				//测试InitList函数接口的功能,同时获取此时链表的状态信息
	length = obj.ListLength(L);
	cout << "此时的循环链表长度length为:" << length << endl;
	int BOOL = obj.ListEmpty(L);
	cout << "ListEmpty的值为0说明链表非空,为1说明链表为空!" << endl;
	cout << "BOOL = " << BOOL << endl;
	obj.DispList(L);
	cout << endl;

	obj.CreateList(L, arr, len);		//测试CreateList函数接口功能,同时获取此时链表的状态信息
	length = obj.ListLength(L);
	cout << "ListLength获取链表长度length为:" << length << endl;
	BOOL = obj.ListEmpty(L);
	cout << "ListEmpty的值为0说明链表非空,为1说明链表为空!" << endl;
	cout << "BOOL = " << BOOL << endl;
	obj.DispList(L);
	cout << endl;

	int locate = 0, e = 0;			//测试GetElem函数接口
	locate = 7;
	obj.GetElem(L, locate, e);
	cout << "GetElem查询单链表后查找到的元素e值为:" << e << "\n\n";

	locate = 0, e = 8;					//按照元素e的值查询循环单链表
	obj.LocateList(L, e, locate);		//测试LocateList函数接口
	cout << "LocateList查询单链表后的locate值为:" << locate << "\n\n";

	locate = 6, e = 6;					//将元素6插入到链表的指定位置(逻辑位置)
	obj.InsertList(L, locate, e);
	len = obj.ListLength(L);
	cout << "此时ListLength获取的链表长度length为:" << len << endl;
	obj.DispList(L);
	cout << endl;

	locate = 10, e = 0;					//删除链表中指定位置的元素
	obj.DeleteList(L, locate, e);		//测试DeleteList函数接口
	cout << "DeleteList删除的节点值e为:" << e << endl;
	len = obj.ListLength(L);
	cout << "此时ListLength获取的链表长度length为:" << len << endl;
	obj.DispList(L);
	cout << endl;

	obj.DestoryList(L);
	return 0;
}

就离谱,我这段代码问题出现在DispList函数 身上,问题出现在执行InsertList函数后,这时的再执行双向循环链表就出错。这是错误信息

我实在不知道问题出在哪,Insert和DIsplis函数来来回回看了很多遍,求路过的大神给点意见,谢谢了哈

  • 写回答

1条回答 默认 最新

  • 努力学习的阿信 2021-05-24 15:19
    关注

    晕死,原来是DeleteList函数中寻找第一个插入的节点是出错

     

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 12月7日
  • 已采纳回答 11月29日

悬赏问题

  • ¥15 用verilog实现tanh函数和softplus函数
  • ¥15 求京东批量付款能替代天诚
  • ¥15 slaris 系统断电后,重新开机后一直自动重启
  • ¥15 51寻迹小车定点寻迹
  • ¥15 谁能帮我看看这拒稿理由啥意思啊阿啊
  • ¥15 关于vue2中methods使用call修改this指向的问题
  • ¥15 idea自动补全键位冲突
  • ¥15 请教一下写代码,代码好难
  • ¥15 iis10中如何阻止别人网站重定向到我的网站
  • ¥15 滑块验证码移动速度不一致问题