循环链表模板类

#pragma once

#include <iostream>

template<typename T>
struct CircLinkNode {
	T data;
	CircLinkNode<T>* link;
	CircLinkNode(CircLinkNode<T>* next = nullptr) :data(0), link(next) {}
	CircLinkNode(T d, CircLinkNode<T>* next = nullptr) :data(d), link(next) {}
};

template<typename T>
class CircList
{
public:
	CircList();												//构造函数
	CircList(const T& x);									//构造函数
	CircList(CircList<T>& L);								//拷贝构造
	~CircList();											//析构函数
	void makeEmpty();										//将链表置空
	int Length()const;										//计算循环链表长度
	bool IsEmpty() { return first->link == first ? true : false; }
															//判表空否
	CircLinkNode<T>* getHead()const;						//返回附加头结点地址
	void setHead(CircLinkNode<T>* p);						//设置附加头结点地址
	CircLinkNode<T>* Search(T x);							//搜索含数据x的元素
	CircLinkNode<T>* Locate(int i)const;					//搜索第i个元素的地址
	bool getData(int i, T& x)const;							//取出第i个元素的地址
	void setData(int i, T& x);								//用x修改第i个元素的值
	bool Insert(int i, T& x);								//在第i个元素后插入x
	bool Remove(int i, T& x);								//删除第i个元素,x返回该元素的值
	void output();											//输出
	CircList<T>& operator=(CircList<T>& L);					//重载运算符=
	void inputFront(T endTag);								//前插法建立单链表
	void inputRear(T endTag);								//后插法建立单链表
private:
	CircLinkNode<T>* first, * last;						//头指针,尾指针
};

template<typename T>
inline CircList<T>::CircList()
{
	first = new CircLinkNode<T>;
	first->link = first;
	last = first;
}

template<typename T>
inline CircList<T>::CircList(const T& x)
{
	first = new CircLinkNode<T>(x);
	first->link = first;
	last = first;
}

template<typename T>
inline CircList<T>::CircList(CircList<T>& L)
{
	//拷贝构造函数
	T value;
	CircLinkNode<T>* srcptr = L.getHead();					//被赋值表的附加头结点地址
	CircLinkNode<T>* destptr = first = new CircLinkNode<T>;
	while (srcptr->link != L.first)							//逐个结点复制
	{
		value = srcptr->link->data;
		destptr->link = new CircLinkNode<T>(value);
		destptr = destptr->link;
		srcptr = srcptr->link;
	}
	last = srcptr;
	destptr->link = first;	
}

template<typename T>
inline CircList<T>::~CircList()
{
	makeEmpty();
	if (first != nullptr) delete first;
}

template<typename T>
inline void CircList<T>::makeEmpty()
{
	//将链表置位空表
	CircLinkNode<T>* q;
	while (first->link != first)
	{
		q = first->link;
		first->link = q->link;
		delete q;
	}
	last = first;
}

template<typename T>
inline int CircList<T>::Length() const
{
	//计算带附加头结点的单链表的长度
	CircLinkNode<T>* p = first->link;
	int count = 0;
	while (p != first)										//循链扫描,寻找链尾
	{
		p = p->link;
		count++;
	}
	return count;
}

template<typename T>
inline CircLinkNode<T>* CircList<T>::getHead() const
{
	return first;
}

template<typename T>
inline void CircList<T>::setHead(CircLinkNode<T>* p)
{
	CircLinkNode<T>* current = first;
	while (current->link != first)
	{
		if (current->link == p) break;						//循链找p指针
		else current = current->link;
	}
	first = current->link;
	last = current;
}

template<typename T>
inline CircLinkNode<T>* CircList<T>::Search(T x)
{
	//在表中搜索含数据x的节点,搜索成功时函数返回该节点地址;否则返回first值。
	CircLinkNode<T>* current = first->link;
	while (current != first)
	{
		if (current->data == x) break;						//循链找含x结点
		else current = current->link;
	}
	return current;
}

template<typename T>
inline CircLinkNode<T>* CircList<T>::Locate(int i) const
{
	//定位函数。返回表中第i个元素的地址。若i<0或i超过表中结点个数,则返回first。
	if (i < 0) return first;								//i不合理
	CircLinkNode<T>* current = first->link;
	int k = 1;
	while (current != first && k < i)						//循链找第i个结点
	{
		current = current->link;
		k++;
	}
	return current;											//返回第i个结点地址,若返回first,表示i值太大
}

template<typename T>
inline bool CircList<T>::getData(int i, T& x) const
{
	//取出链表中第i个元素的值。
	if (i <= 0) return false;								//i值太小
	CircLinkNode<T>* current = Locate(i);
	if (current == first) return false;						//i值太大
	else
	{
		x = current->data;
		return true;
	}
}

template<typename T>
inline void CircList<T>::setData(int i, T& x)
{
	//给链表中的第i个元素赋值x。
	if (i <= 0) return;										//i值太小
	CircLinkNode<T>* current = Locate(i);
	if (current == first) return;							//i值太大
	else current->data = x;
}

template<typename T>
inline bool CircList<T>::Insert(int i, T& x)
{
	//将新元素x插入在链表中第i个结点之后。
	CircLinkNode<T>* current = Locate(i);
	if (current == first) return false;						//插入不成功
	CircLinkNode<T>* newNode = new CircLinkNode<T>(x);
	if (newNode == nullptr)
	{
		std::cerr << "存储分配错误!" << std::endl;
		exit(1);
	}
	newNode->link = current->link;
	current->link = newNode;
	if (newNode->link == first) last = newNode;
	return true;											//插入成功
}

template<typename T>
inline bool CircList<T>::Remove(int i, T& x)
{
	//将链表中的第i个元素删去,通过引用型参数x返回该元素的值。
	CircLinkNode<T>* current = Locate(i - 1);
	if (current == first || current->link == first)	return false;
	//删除不成功
	CircLinkNode<T>* del = current->link;					//重新拉链,将被删结点从链中摘下
	current->link = del->link;
	x = del->data;
	delete del;												//取出被删结点中的数据值
	if (current->link == first) last = current;
	return true;
}

template<typename T>
inline void CircList<T>::output()
{
	//循环链表的输出函数:将循环链表中所有数据按逻辑顺序输出到屏幕上。
	std::cout << "链表中的元素为: ";
	CircLinkNode<T>* current = first->link;
	while (current != first)
	{
		std::cout << current->data << " ";
		current = current->link;
	}
	std::cout << std::endl;
}

template<typename T>
inline CircList<T>& CircList<T>::operator=(CircList<T>& L)
{
	//重载函数:赋值操作,形式如 A = B,其中 A 是调用此操作的List对象,B 是参数表中的
	//引用型参数L结合的实参。
	makeEmpty();
	T value;
	CircLinkNode<T>* srcptr = L.getHead();					//被复制表的附加头结点地址
	CircLinkNode<T>* destptr = first = new CircLinkNode<T>;
	while (srcptr->link != L.first)							//逐个结点复制
	{
		value = srcptr->link->data;
		destptr->link = new CircLinkNode<T>(value);
		destptr = destptr->link;
		srcptr = srcptr->link;
	}
	destptr->link = first;
	last = destptr;
	return *this;											//返回操作对象地址
}

template<typename T>
inline void CircList<T>::inputFront(T endTag)
{
	//endTag是约定的输入序列结束的标志。如果输入序列是正整数,endTag可以是0或负数;
	//如果输入序列是字符,endTag可以是字符集中不会出现的字符,如"\0"。
	CircLinkNode<T>* newNode;
	T val;
	makeEmpty();
	std::cin >> val;
	while (val != endTag)
	{
		newNode = new CircLinkNode<T>(val);					//创建新结点
		if (newNode == nullptr)
		{
			std::cerr << "存储分配错误!" << std::endl;
			exit(1);
		}
		newNode->link = first->link;
		first->link = newNode;								//插入到表最前端
		if (last == first)
		{
			last = newNode;
		}
		std::cin >> val;
	}
}

template<typename T>
inline void CircList<T>::inputRear(T endTag)
{
	//endTag是约定的输入序列结束的标志
	CircLinkNode<T>* newNode;
	T val;
	makeEmpty();
	std::cin >> val;	
	while (val != endTag)									//last指向表尾
	{
		newNode = new CircLinkNode<T>(val);
		if (newNode == nullptr)
		{
			std::cerr << "存储分配错误!" << std::endl;
			exit(1);
		}		
		last->link = newNode;
		last = newNode;
		std::cin >> val;									//插入到表末端
	}
	last->link = first;
}

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值