循环双向链表的C++实现

循环双向链表的增删查改等基本操作

#include<iostream>
#include<assert.h>
using namespace std;
typedef int DataType;
struct ListNode
{
	DataType _data;
	ListNode* _prev;
	ListNode* _next;
	ListNode(const DataType& x)
		:_data(x)
		,_prev(NULL)
		,_next(NULL)
	{}
	ListNode()
		:_data(0)
		,_prev(NULL)
		,_next(NULL)
	{}
};
class List
{
private:
	ListNode _head;
public:
	List()
	{
		_head._prev=&_head;
		_head._next=&_head;
	}
	~List()
	{
		clear();
	}
	void clear()
	{
		assert(_head._next);
		ListNode* cur=_head._next;
		while(cur!=&_head)
		{
			ListNode* del=cur;
			cur=cur->_next;
			delete del;
			del=NULL;
		}
	}
	void PushBack(const DataType& x)
	{
		ListNode* _tail=_head._prev;
		ListNode* tmp=new ListNode(x);
		_tail->_next=tmp;
		tmp->_prev=_tail;
		tmp->_next=&_head;
		_head._prev=tmp;
	}
	void PopBack()
	{
		assert(_head._next);
		if(_head._next==_head._prev)
		{
			delete _head._next;
			_head._next=&_head;
		}
		else
		{
			ListNode* _cur=_head._prev;
			ListNode* _tail=_cur->_prev;
			_tail->_next=&_head;
			_head._prev=_tail;
			delete _cur;
			_cur=NULL;
		}
	}
	void PushFront(const DataType& x)
	{
		ListNode* tmp=new ListNode(x);
		ListNode* cur=_head._next;
		_head._next=tmp;
		tmp->_prev=&_head;
		if(cur==&_head)
		{
			_head._prev=tmp;
			tmp->_next=&_head;
		}
		else
		{
			cur->_prev=tmp;
			tmp->_next=cur;
		}
	}
	void PopFront()
	{
		assert(_head._next);
		ListNode *cur=_head._next;
		_head._next=cur->_next;
		cur->_prev=&_head;
		delete cur;
		cur=NULL;
	}
	ListNode* Find(const DataType& x)
	{
		assert(_head._next);
		ListNode* cur=_head._next;
		while(cur!=&_head)
		{
			if(cur->_data!=x)
			{
				cur=cur->_next;
			}
			else
			{
				return cur;
			}
		}
		cout<<"x不存在"<<endl;
		return NULL;
	}
	void Erase(ListNode* pos)
	{
		assert(pos);
		ListNode* prev=pos->_prev;
		ListNode* next=pos->_next;
		if(pos->_prev==pos->_next)
		{
			_head._next=&_head;
			_head._prev=&_head;
		}
		else
		{
			prev->_next=next;
			next->_prev=prev;
		}
	}
	void Remove(const DataType& x)
	{
		assert(_head._next);
		ListNode* cur=_head._next;
		while(cur!=&_head)
		{
			if(cur->_data!=x)
			{
				cur=cur->_next;
			}
			else
			{
				ListNode* prev=cur->_prev;
				ListNode* next=cur->_next;
		        if(cur->_prev==cur->_next)
		        {
			       _head._next=&_head;
			       _head._prev=&_head;
				   return;
		        }
				else
				{
					prev->_next=next;
					next->_prev=prev;
					return;
				}
			}
		}
		cout<<"x不存在"<<endl;
		return;
	}
	void Print()
	{
		assert(_head._next);
		ListNode *cur=_head._next;
		while(cur!=&_head)
		{
			cout<<cur->_data<<"->";
			cur=cur->_next;
		}
		cout<<"Tail"<<endl;
	}
};
void Test1()
{
	List l;
	//l.PushBack(1);
	//l.PushBack(2);
	//l.PushBack(3);
	////l.Print();
	//l.PopBack();
	//l.PopBack();
	//
	//l.PopBack();
	//l.PopBack();
	//l.Print();
	l.PushFront(1);
	l.PushFront(2);
	l.PushFront(3);
	//l.Print();
	l.PopFront();
	l.PopFront();
	l.PopFront();
	l.PopFront();
	l.Print();
}
void Test2()
{
	List l;
	l.PushBack(1);
	l.PushBack(2);
	l.PushBack(3);
	//ListNode* pos=l.Find(1);
	//ListNode* pos=l.Find(2);

	ListNode* pos=l.Find(4);
	l.Erase(pos);
	l.Print();
}
void Test3()
{
	List l;
	l.PushBack(1);
	l.PushBack(2);
	l.PushBack(3);
	l.Remove(1);
        l.Remove(2);
	l.Remove(3);
	l.Remove(4);
	l.Print();
}
int main()
{
	//Test1();
	//Test2();
	Test3();
	system("pause");
	return 0;
}
时间: 2024-07-30 13:37:45

循环双向链表的C++实现的相关文章

经典算法学习——非循环双向链表实现冒泡排序(不带头结点)

我在前面两篇博客<经典算法学习--单链表(不带头结点)实现冒泡排序><经典算法学习--单链表实现冒泡排序(带头结点)>中详细描述了分别使用带头结点和不带头结点的单链表实现了冒泡排序,让我们对单链表和冒泡排序有了理性的认识.今天我们将会来使用不带头结点的非循环双向链表来实现冒泡排序,在处理过程中,这种冒泡比前面两种更为简单高效.代码上传至 https://github.com/chenyufeng1991/DoubleLinkedList_BubbleSort . 核心代码如下: /

数据结构——树——二叉查找树转换成排序的循环双向链表

题目描述 输入一棵二叉查找树,将该二叉查找树转换成一个排序的循环双向链表. 要求不能创建任何新的结点,只调整指针的指向,也不能开辟新的存储空间O(1) 题目分析 首先照旧我们问题的解决思路,首先简化问题.(前提你应该了解二叉查找树和双向链表) 如果没有任何的要求,那么我们自然会想到遍历整棵树然后排序出来之后重新构建一个链表即可,你想要什么样的都可以. 那么我们需要考虑的就是如何遍历? 然后慢慢复杂问题,不能新建立,那么就要在原来的基础上改,怎么改才能变过去呢? 这时,我要教你对于树的问题,有一招

双向链表(4) - 排序二叉树转换为循环双向链表

构建一个递归函数treeToList(Node root),将一棵已排序的二叉树,调整内部指针,使之从外面看起来,是一个循环双向链表.其中前向指针存储在"small"区域,后向指针存储在"large"区域.链表需要进行调整进行升序排序,并返回链表头指针. 下面的这篇文章详细解释了这个转换的过程. http://cslibrary.stanford.edu/109/TreeListRecursion.html 以下是对这篇文章的翻译: The Great Tree-L

(含头指针以及尾指针)循环双向链表各类功能的实现

对循环双链表实现下述功能: void meau(); //菜单函数 void Initlist(List *list); //初始化 void show(List *list); //打印链表内容 bool Push_back(List *list,ElemType x); //尾插法 bool Push_front(List *list,ElemType x);//头插法 bool Isempty(List *list); //判断链表是否为空 bool Pop_back(List *list

循环双向链表的

链表的使用 初级版: 结构体 struct data{ struct data* next; int data; }; head=p1->p2->p3->p4->NULL 需要删除节点p3时就很麻烦,我们需要从头去遍历,找到next指针为p3时将next指针指向p3的next: 为此方便起见,我们可以使用双向链表进行实现.操作会简单许多 NULL<-head=>p1<=>p2<=>p3<=>p4->NULL; 删除p3节点时,我

线性链表其他种类(静态,双向,循环)的存储结构和常见操作

一.静态单链表 在不支持动态空间分配的环境中,要使用链表存储数据,那么可采用静态链表的方法:即在一块预分配的存贮空间中,用下标作为指针链来构成链式结构. //既然是静态链表,那么可以使用一维数组实现存储,java没有指针,那么就用这来使用链表结构 //在不支持动态空间分配的环境中,要使用链式结构技术,可采用静态链表的方法:即在一块预分配的存贮空间中,用下标作为指针. //存储结构:在数组中增加一个“指针”域,存放下一元素在数组中的下标.且0为代表空指针 //设S为SLinkList型变量,若第i

一步一步写算法(之双向链表)

原文:一步一步写算法(之双向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面的博客我们介绍了单向链表.那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针.双向链表相比较单向链表,主要有下面几个特点: (1)在数据结构中具有双向指针 (2)插入数据的时候需要考虑前后的方向的操作 (3)同样,删除数据的是有也需要考虑前后方向的操作 那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下: (

C实现头插法和尾插法来构建非循环双链表(不带头结点)

在实际使用中,双链表比单链表方便很多,也更为灵活.对于不带头结点的非循环双链表的基本操作,我在<C语言实现双向非循环链表(不带头结点)的基本操作>这篇文章中有详细的实现.今天我们就要用两种不同的方式头插法和尾插法来建立双链表.代码上传至  https://github.com/chenyufeng1991/HeadInsertAndTailInsertDoubleList  . 核心代码如下: //尾插法创建不带头结点的非循环双向链表 Node *TailInsertCreateList(No

01-(2)数据结构- 一步一步写算法(之双向链表)

前面的博客我们介绍了单向链表.那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针.双向链表相比较单向链表,主要有下面几个特点: (1)在数据结构中具有双向指针 (2)插入数据的时候需要考虑前后的方向的操作 (3)同样,删除数据的是有也需要考虑前后方向的操作 那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下: (1)定义双向链表的基本结构 [cpp] view plain copy typedef struct _DOUBLE_LINK_NODE {