C++——实现双向循环链表(带头结点)
程序员文章站
2024-03-22 11:20:40
...
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
简单的画一个双向循环简易图:
下面就用C++实现一下基本操作
当然也有 C 语言 版的,只是单链表操作
(https://blog.csdn.net/Paranoid_cc/article/details/79707761)
先分开写吧
1、四个重要的函数:构造函数、拷贝构造函数、赋值运算符重载、析构函数。
//构造函数
List(size_t n,const DataType& data)
{
_CreateHead();
for (size_t i = 0; i < n; ++i)
PushBack(data);
}
List(DataType* first, DataType* last)
{
_CreateHead();
while (first != last)
PushBack(*first++);
}
//拷贝构造函数
List(const List& L)
{
_pHead = new Node();
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
Node* pCur = L._pHead->_pNext;
while (pCur != L._pHead)
{
this->PushBack(pCur->_data);
pCur = pCur->_pNext;
}
}
//赋值运算符重载
List& operator=(const List& s)
{
if (this != &s)
{
this->Clear();
Node* pCur = s._pHead->_pNext;
while (pCur != s._pHead)
{
this->PushBack(pCur->_data);
pCur = pCur->_pNext;
}
}
return *this;
}
//析构函数
~List()
{
Clear();
delete _pHead;
_pHead = NULL;
}
2、对链表的数据的操作(删除和插入)
//尾插
void PushBack(const DataType& data)
{
Node* pNewNode = new Node(data);
pNewNode->_pPre = _pHead->_pPre;
pNewNode->_pNext = _pHead;
_pHead->_pPre = pNewNode;
pNewNode->_pPre->_pNext = pNewNode;
}
//尾删
void PopBack()
{
if (Empty())
return;
Node* pDelNode = _pHead->_pPre;
pDelNode->_pPre->_pNext = _pHead;
_pHead->_pPre = pDelNode->_pPre;
delete pDelNode;
}
//头插
void PushFront(const DataType& data)
{
Node* pNewNode = new Node(data);
pNewNode->_pNext = _pHead->_pNext;
pNewNode->_pPre = _pHead;
_pHead->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
}
//头删
void PopFront()
{
if (Empty())
return;
Node* pDelNode = _pHead->_pNext;
_pHead->_pNext = pDelNode->_pNext;
pDelNode->_pNext->_pPre = _pHead;
delete pDelNode;
}
//任意位置插入
Node* Insert(Node* pos, const DataType& data)
{
Node* pNewNode = new Node(data);
pNewNode->_pNext = pos;
pNewNode->_pPre = pos->_pPre;
pNewNode->_pPre->_pNext = pNewNode;
pos->_pPre = pNewNode;
return pNewNode;
}
//任意位置删除
Node* Erase(Node* pos)
{
if (NULL == pos || pos == _pHead)
return NULL;
Node* ret = pos->_pNext;
pos->_pPre->_pNext = pos->_pNext;
pos->_pNext->_pPre = pos->_pPre;
delete pos;
return ret;
}
3、对链表空间的操作
//链表的大小
size_t Size()const
{
Node* pCur = _pHead->_pNext;
size_t count = 0;
while (pCur != _pHead)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
//判空
bool Empty()const
{
return _pHead->_pNext == _pHead;
}
//改变链表的大小
void ReSize(size_t newSize, const DataType& data = DataType())
{
int gap = newSize - Size();
if (gap > 0)//链表元素增多了
{
while (gap--)
PushBack(data);//尾插
}
else
{
while (gap++)//链表元素减少了
PopBack();
}
}
下面给出完成的操作代码以及测试代码和结果图
#define _CRT_SECURE_NO_WARNINGS
#define NULL 0
#include<iostream>
#include<string.h>
#include<assert.h>
using namespace std;
//双向循环链表(带头结点)
typedef int DataType;
struct Node
{
Node* _pNext;
Node* _pPre;
DataType _data;
//构造函数
Node(const DataType& data = DataType())
:_pNext(NULL)
, _pPre(NULL)
, _data(data)
{}
};
class List
{
public:
List()
{
_CreateHead();
}
//构造函数
List(size_t n,const DataType& data)
{
_CreateHead();
for (size_t i = 0; i < n; ++i)
PushBack(data);
}
List(DataType* first, DataType* last)
{
_CreateHead();
while (first != last)
PushBack(*first++);
}
//拷贝构造函数
List(const List& L)
{
_pHead = new Node();
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
Node* pCur = L._pHead->_pNext;
while (pCur != L._pHead)
{
this->PushBack(pCur->_data);
pCur = pCur->_pNext;
}
}
//赋值运算符重载
List& operator=(const List& s)
{
if (this != &s)
{
this->Clear();
Node* pCur = s._pHead->_pNext;
while (pCur != s._pHead)
{
this->PushBack(pCur->_data);
pCur = pCur->_pNext;
}
}
return *this;
}
//析构函数
~List()
{
Clear();
delete _pHead;
_pHead = NULL;
}
//尾插
void PushBack(const DataType& data)
{
Node* pNewNode = new Node(data);
pNewNode->_pPre = _pHead->_pPre;
pNewNode->_pNext = _pHead;
_pHead->_pPre = pNewNode;
pNewNode->_pPre->_pNext = pNewNode;
}
//尾删
void PopBack()
{
if (Empty())
return;
Node* pDelNode = _pHead->_pPre;
pDelNode->_pPre->_pNext = _pHead;
_pHead->_pPre = pDelNode->_pPre;
delete pDelNode;
}
/*
void PushBack(const DataType& data)//尾插
{
Node* pNewNode = new Node(data);
if (NULL == _pHead)
{
_pHead = pNewNode;
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
else
{
Node* pTail = _pHead->_pPre;
pTail->_pNext = pNewNode;
pNewNode->_pPre = pTail;
pNewNode->_pNext = _pHead;
_pHead->_pPre = pNewNode;
}
}
void PopBack()//尾删
{
if (NULL == _pHead)//链表为空
return;
else if (_pHead->_pNext == _pHead)//只有一个结点
{
delete _pHead;
_pHead = NULL;
}
else//有多个结点
{
Node* pPreTail = _pHead->_pPre->_pPre;
delete pPreTail;
pPreTail->_pNext = _pHead;
_pHead->_pPre = pPreTail;
}
}
*/
//头插
void PushFront(const DataType& data)
{
Node* pNewNode = new Node(data);
pNewNode->_pNext = _pHead->_pNext;
pNewNode->_pPre = _pHead;
_pHead->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
}
//头删
void PopFront()
{
if (Empty())
return;
Node* pDelNode = _pHead->_pNext;
_pHead->_pNext = pDelNode->_pNext;
pDelNode->_pNext->_pPre = _pHead;
delete pDelNode;
}
//任意位置插入
Node* Insert(Node* pos, const DataType& data)
{
Node* pNewNode = new Node(data);
pNewNode->_pNext = pos;
pNewNode->_pPre = pos->_pPre;
pNewNode->_pPre->_pNext = pNewNode;
pos->_pPre = pNewNode;
return pNewNode;
}
//任意位置删除
Node* Erase(Node* pos)
{
if (NULL == pos || pos == _pHead)
return NULL;
Node* ret = pos->_pNext;
pos->_pPre->_pNext = pos->_pNext;
pos->_pNext->_pPre = pos->_pPre;
delete pos;
return ret;
}
size_t Size()const
{
Node* pCur = _pHead->_pNext;
size_t count = 0;
while (pCur != _pHead)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
bool Empty()const
{
return _pHead->_pNext == _pHead;
}
void ReSize(size_t newSize, const DataType& data = DataType())
{
int gap = newSize - Size();
if (gap > 0)//链表元素增多了
{
while (gap--)
PushBack(data);//尾插
}
else
{
while (gap++)//链表元素减少了
PopBack();
}
}
//取出链表第一个元素的数据
DataType& Front()
{
assert(!Empty());
return _pHead->_pNext->_data;
}
const DataType& Front()const
{
assert(!Empty());
return _pHead->_pNext->_data;
}
DataType& Back()
{
assert(!Empty());
return _pHead->_pPre->_data;
}
const DataType& Back() const
{
assert(!Empty());
return _pHead->_pPre->_data;
}
void Clear()
{
Node* pCur = _pHead->_pNext;
while (pCur != _pHead)
{
pCur = Erase(pCur);
}
}
private:
void _CreateHead()
{
_pHead = new Node;
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
//打印函数
friend ostream& operator<<(ostream& _cout, const List& l)
{
Node* pCur = l._pHead->_pNext;
while (pCur != l._pHead)
{
_cout << pCur->_data << " ";
pCur = pCur->_pNext;
}
return _cout;
}
private:
Node* _pHead;
};
void TestList()
{
List l1;
List l2(10,5);
cout << l2 << endl;
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List l3(array, array + sizeof(array) / sizeof(DataType));
cout << l3.Size() << endl;
cout << l3 << endl;
cout << l3.Front() << endl;
cout << l3.Back() << endl;
l3.ReSize(5);
cout << l3.Size() << endl;
cout << l3 << endl;
cout << l3.Front() << endl;
cout << l3.Back() << endl;
l3.ReSize(15,6);
cout << l3.Size() << endl;
cout << l3 << endl;
cout << l3.Front() << endl;
cout << l3.Back() << endl;
}
int main()
{
TestList();
return 0;
}
结果图
后面会发出C++实现的动态顺序表的操作
上一篇: 用模板实现顺序表和带头结点的双向循环链表