您的位置:首页 > 理论基础 > 数据结构算法

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

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

给出双链表的一般结构:





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

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

头文件:

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: