单链表结构为我们提供方便分数据插入和删除工作,美中不足的是查询数据不方便,对于单链表查找数据至少要遍历一边. 为此我们提出双链表结构,从而方便的查询数据.
给出双链表的一般结构:
一种是带头结点(哨兵位)的管理方式,另一种是带管理节点管理方式。 但是我们不建议采用管理节点和头结点并存的方式(管理较前两者复杂)。
提供带头结点的双循环链表模版类实现,代码如下:
头文件:
#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