大话数据结构 —— 单循环链表 C#、C++代码实现

 


单循环链表


 单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环。

和单链表相比,循环单链表的长处是从链尾到链头比较方便。当要处理的数据元素序列具有环型结构特点时,适合于采用循环单链表。

 单循环链表的初始化操作:示意图

             

非空表示意图:

 假如终端结点用尾指针 rear 指示, 则查找终端结点是 O(1), 而开始结点,其实就是 rear->next->next, 时间复杂度也是 O(1)。

下面用C++ 代码实现单循环链表:

#include<iostream>
#include<cassert>
using namespace std;

using   ElemType = int;
using  Status = void;
class CirLinkList
{
public:
	struct Node
	{
		ElemType m_data;
		Node *m_next;
	};
	enum State
	{
		TT_ERROR = 0,
		TT_OK = 1
	};
public:
	CirLinkList();
	~CirLinkList();
	ElemType insertAt(ElemType i, ElemType elem);
	ElemType removeAt(ElemType i, ElemType &elemOut);
	ElemType getAt(ElemType i, ElemType &elemOut);
	ElemType locationElemAt(ElemType &i, ElemType elemOut);//查找与e相等的元素,返回第一个与e相等元素在线性表中的下标,否则,返回0
	Status getLength()const;
	Status isEmpty()const;
	ElemType destroy();
	ElemType clear();
	Status show();
	Status backRemoveElemAt();   //尾删
	Status backInsertElemAt(ElemType elem);//尾插
	Status headInsetElemAt(ElemType elem); //头插
	Status headRemoveElemAt(); //头删
	Status reserve();  //逆置链表 

	ElemType priorElemAt(ElemType cur_e, ElemType &pri_e);//若cur_e是链表的数据元素,且不是第一个,则用pre_e返回它的前驱
	ElemType nextElemAt(ElemType cur_e, ElemType &Nex_e); //若cur_e是链表的数据元素,且不是最后一个,则用next_e返回它的后继,
	Status createTail(ElemType *datas, ElemType length);//创建长度为length的链表,数据通过数组指定,这里采用尾插法
	Status createHead(ElemType *datas, ElemType length);  //头插法
	Node *prevElemIndexAt(Node *nodeElem);     //返回nodeElem指向的前面一个节点
	ElemType modify(ElemType findElem, ElemType replaceElem);    //把原有的elem1修改成elem2
	Node *find(ElemType preElemAddress);       //返回要查找元素的前面一个的地址
private:
	Node *m_head;
	Node *m_tail;
};
CirLinkList::CirLinkList()
{
	m_head = new Node;
	assert(m_head != nullptr);
	m_head->m_next = m_head;
	m_tail = m_head;
	cout << "\n********************单向的循环列表初始化成功!************************" << endl;
}
CirLinkList::~CirLinkList()
{
	this->destroy();
}
Status CirLinkList::createHead(ElemType *datas, ElemType length)  //头插法
{
	m_head->m_data = length;
	Node *s = new Node;
	if (m_head->m_next == m_head)
	{
		//this->insertAt(1,datas[0]); 利用insertAt 函数创建头插法的第一个结点
		s->m_data = datas[0];
		m_head->m_next = s;
		s->m_next = m_head;
		m_tail = s;
	}
	//Node *s = m_head->m_next;
	for (int i = 1; i < length; ++i)
	{
		Node *p = new Node;
		p->m_data = datas[i];
		p->m_next = s;
		m_head->m_next = p;
		s = p;
	}
}
CirLinkList::Node *CirLinkList::find(ElemType preElemAddress)       //返回要查找元素的前面一个的地址
{
	Node *p = m_head;
	while ((m_tail != p) && (m_head) != (p->m_next) && (preElemAddress) != (p->m_next->m_data))
	{
		p = p->m_next;                   //循环结束,p指向x的前面一个元素
	}
	if (m_head == p->m_next)          //如果p指向最后一个元素,说明没有找到
	{
		cout << "没找到该元素!" << endl;
		return nullptr;
	}
	return p;
}
ElemType CirLinkList::modify(ElemType findElem, ElemType replaceElem)    //把原有的elem1修改成elem2
{
   if (!(m_head->m_data))
	{
		return TT_ERROR;
	}
	Node *p = find(findElem);
	if (nullptr != p)
	{
		p->m_next->m_data = replaceElem;
	}
	return TT_OK;
}
CirLinkList::Node *CirLinkList::prevElemIndexAt(Node *nodeElem)  //返回nodeElem指向的前面一个节点
{
	if (nodeElem != m_head)
	{
		Node *q = m_head->m_next;
		while (q != m_head && q->m_next != nodeElem)  //依次往后移,知道尾指针的前面一个节点
		{
			q = q->m_next;
		}
		if (q->m_next == nodeElem)
		{
			return q;
		}
	}
	return nullptr;
}
Status CirLinkList::reserve()  //逆置链表 
{
	/*  自己编写的代码,没通过
	m_tail->m_next = nullptr;
	Node *p = m_head->m_next;
	m_tail = p;

	m_head->m_next = nullptr;
	Node *s = new Node;
	Node *m = s;
	while (p)
	{
		p->m_next = s;
		s = p;
		p = p->m_next;
	}
	m_head->m_next = p;
	delete m;*/

	if (!(m_head->m_data) || (m_head->m_data == 1))
	{
		cout << "链表中没有元素,或者只有一个元素,无法反转列表!" << endl;
		system("pause");
		exit(0);
	}
	Node *s = new Node;    //建立一个节点
	s->m_next = m_tail;
	Node *p = m_tail;
	while (m_tail != m_head->m_next)        //把原链表的尾节点到第一个节点依次连接到新节点上
	{
		m_tail = prevElemIndexAt(m_tail);
		m_tail->m_next = m_head;
		p->m_next = m_tail;
		p = p->m_next;
	}
	p->m_next = s;              //p指向第一个节点,即新链表的最后一个节点,尾指针的next指向头结点s,链表结束
	delete m_head;         //释放原来的头结点
	m_head = s;           //把s变成新的头指针
}
ElemType CirLinkList::priorElemAt(ElemType cur_e, ElemType &pri_e)//若cur_e是链表的数据元素,且不是第一个,则用pre_e返回它的前驱
{
	if (!(m_head->m_data) || (m_head->m_data == 1))
	{
		return TT_ERROR;
	
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值