【C++数据结构】模版类实现双循环链表的基本操作

单链表结构为我们提供方便分数据插入和删除工作,美中不足的是查询数据不方便,对于单链表查找数据至少要遍历一边.  为此我们提出双链表结构,从而方便的查询数据.


给出双链表的一般结构:




一种是带头结点(哨兵位)的管理方式,另一种是带管理节点管理方式。 但是我们不建议采用管理节点和头结点并存的方式(管理较前两者复杂)。



提供带头结点的双循环链表模版类实现,代码如下:


头文件:

#pragma once
#include<iostream>  

using namespace std;

template<class _T>
class DCList
{
protected:
	struct Node;
	friend struct Node;
	typedef _T* _ptr;
	typedef Node* _NodePtr;

	struct Node
	{
		_NodePtr _Prev;
		_NodePtr _Next;
		_T _Value;
	};
private:
	size_t Size;
	_NodePtr Handle;


public:

	DCList() :Size(0), Handle(_BuyNode())
	{}
	~DCList()
	{
		clear();
		_FreeNode(Handle);
		Size = 0;
	}

public:

	bool IsEmpty()
	{
		return Size == 0;
	}

	size_t length()
	{
		return Size;
	}

	_NodePtr& begin()
	{
		return Handle->_Next;
	}

	_NodePtr& end()
	{
		return Handle;
	}

	void Insert(_NodePtr _P, const _T& v)
	{
		_NodePtr _S = _BuyNode(_P, _P->_Prev);
		_P->_Prev = _S;
		_S->_Prev->_Next = _S;
		_S->_Value = v;
		++Size;
	}

	bool Insert_val(const _T& x)
	{
		_NodePtr _P = _BuyNode(NULL,NULL,x);
		Insert_val(_P);
		return true;
	}

	void Insert(_NodePtr _P, _NodePtr _S)
	{
		_S->_Next = _P->_Next;
		_P->_Next->_Prev = _S;
		_P->_Next = _S;
		_S->_Prev = _P;
		if (_P == Handle->_Prev)
		{
			_S->_Next = Handle;
			Handle->_Prev = _S;
		}
		Size++;
	}

	void Insert_val(_NodePtr _Cur)
	{
		_NodePtr _P = Handle;
		while (_P->_Next != end()  && _Cur->_Value > _P->_Next->_Value)
			_P = _P->_Next;
		Insert(_P, _Cur);
	}

	void push_back(const _T& x)
	{
		Insert(end(), x);
	}

	void push_front(const _T& x)
	{
		Insert(begin(), x);
	}

	void ShowList()
	{
		if (IsEmpty())
		{
			cout << "null" << endl;
			return;
		}
			
		_NodePtr cur = begin();
		while (cur != end())
		{
			cout << cur->_Value << "->";
			cur = cur->_Next;
		}
		cout << "null" << endl;
	}

	void erase(_NodePtr _P)  //删除自己
	{
		if (IsEmpty())
			return;
		if (  _P != Handle && _P != NULL)
		{
			_P->_Prev->_Next = _P->_Next;
			_P->_Next->_Prev = _P->_Prev;
			_P->_Prev = _P->_Next = NULL;
		}
		Size--;
		_FreeNode(_P);
		
	}

	void pop_back()
	{
		erase(Handle->_Prev);
	}

	void pop_front()
	{
		erase(Handle->_Next);
	}

	_NodePtr& find(const _T v)
	{
		_NodePtr _Cur = begin();
		while (_Cur != end())
		{
			if (_Cur->_Value == v)
				return _Cur;
		}
		cout << "无此节点,返回头" << endl;
		return Handle;
	}

	void delete_value(const _T _V)
	{
		_NodePtr p;
		while (p = find(_V), p != end())
		{
			erase(p);
		}
	}

	_T& findBypos(size_t pos)
	{
		if (pos > Size)
		{
			cout << "多走 "<< pos/Size<<"圈" << endl;
			pos %= Size;
		}
		_NodePtr p = begin();
		while (p !=end() && pos-1)
		{
			p = p->_Next;
			pos--;
		}
		return p->_Value;
	}

	void clear()
	{
		while (!IsEmpty())
			pop_front();
	}

	void destroy()
	{
		clear();
		_FreeNode(Handle);
		Handle = NULL;
	}

	void merge(DCList& r)
	{
		_NodePtr p = r.begin();
		_NodePtr q;

		r.Handle->_Next = NULL;
		p->_Prev = NULL;

		while (p->_Next !=NULL)
		{
			q = p;
			p = p->_Next;
			q->_Next = NULL;
			p->_Prev = NULL;

			Insert_val(q);
			r.Size--;
		}
		r.begin() = r.end();

	}

	void sort()
	{
		if (length() <= 1)
			return;
		
		_NodePtr _P = begin()->_Next;
		_NodePtr _Q;
		begin()->_Next->_Prev = NULL;
		begin()->_Next = Handle;
		Handle->_Prev = begin();
		Size = 1;

		while (_P != end())
		{
			_Q = _P;
			_P = _P->_Next;
			_Q->_Next = NULL;
			_P->_Prev = NULL;
			Insert_val(_Q);
		}
	}

	void resver()
	{
		if (length() <= 1)
			return;

		_NodePtr _P = begin()->_Next;
		_NodePtr _Q;
		begin()->_Next->_Prev = NULL;
		begin()->_Next = Handle;
		Handle->_Prev = begin();
		Size = 1;

		while (_P != end())
		{
			_Q = _P;
			_P = _P->_Next;
			_Q->_Next = NULL;
			_P->_Prev = NULL;
			
			begin()->_Prev = _Q;
			_Q->_Next = begin();
			Handle->_Next = _Q;
			_Q->_Prev = Handle;
		}
	}
protected:
	_NodePtr _BuyNode(_NodePtr _Narg = NULL, _NodePtr _Parg = NULL, _T v = 0)
	{
		_NodePtr _S = new Node;
		_S->_Next = _Narg != 0 ? _Narg : _S;
		_S->_Prev = _Parg != 0 ? _Parg : _S;
		_S->_Value = v;
		return (_S);
	}
	void _FreeNode(_NodePtr _P)
	{
		delete _P;
		_P = NULL;
	}

};

测试代码:


#include<iostream>  
#include "DCList.h"
using namespace std;


void main()
{

	DCList<int> mylist;

	size_t select = 1;
	int item = 0;
	size_t pos = 0;
	while (select)
	{
		cout << "************************************" << endl;
		cout << "* [0]  quit_system [1] push_back   *" << endl;
		cout << "* [2]  push_front  [3] show_seqlist*" << endl;
		cout << "* [4]  pop_back    [5] pop_front   *" << endl;
		cout << "* [6]  insert_val  [7] delete_val  *" << endl;
		cout << "* [8]  find        [9]  merge      *" << endl;
		cout << "* [10] sort       [11] clear       *" << endl;
		cout << "* [12] destroy    [13] length      *" << endl;
		cout << "* [14] resver     [15] next        *" << endl;
		cout << "* [16] prio                        *" << endl;
		cout << "************************************" << endl;
		cout << "请选择:>";
		cin >> select;
		system("cls");

		switch (select)
		{
		case 1:
			cout << "请输入要插入的数据(-1结束):>";
			while (cin >> item, item != -1)
			{
				mylist.push_back(item);
			}
			break;

		case 2:
			cout << "请输入要插入的数据(-1结束):>";
			while (cin >> item, item != -1)
			{
				mylist.push_front(item);
			}
			break;


		case 3:
			mylist.ShowList();
			break;


		case 4:
			mylist.pop_back();
			break;

		case 5:
			mylist.pop_front();
			break;

		case 6:
			cout << "请输入要插入的数:> " << endl;
			cin >> item;
			mylist.Insert_val(item);
			break;

		case 7:	//error
			cout << "请输入要删除的数:> " << endl;
			cin >> item;
			mylist.delete_value(item);
			break;

		case 8:
			cout << "请输入要查询的位置:> " << endl;
			cin >> pos;
			cout << mylist.findBypos(pos) << endl;
			break;

		case 11:
			cout << "链表将被清空:> " << endl;
			mylist.clear();
			break;

		case 12:
			cout << "链表将被摧毁:> " << endl;
			mylist.destroy();
			break;

		case 13:
			cout<<"长度为:> "<<mylist.length()<<endl;
			break;

		case 14:
			cout << "链表将被逆置 ! " << endl;
//			mylist.resver();
			mylist.ShowList();
			break;

		default:
			break;
		}
	}
}


函数的调用与引用关系如下:


运行环境:VS2015




  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值