1. 程式人生 > >【C++資料結構】模版類實現雙迴圈連結串列的基本操作

【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