上篇文章我们用C++封装了一个动态顺序表:
https://blog.youkuaiyun.com/LSFAN0213/article/details/82082436
这次,我们用C++的方式来封装一个双向循环链表
与我们之前提到的单链表不同的是,双向循环链表的指针域中又多了一个指向前一个结点的pPre指针。这就是双向的意思
循环的意思是,链表的最后一个结点的下一个结点是头结点,头结点的前一个结点是最后一个结点
双向循环链表其他的操作就和单链表是一样的,我们只需注意头结点和尾结点的pNext和pPre就OK
完整代码:
#pragma once
#include <iostream>
using namespace std;
typedef int DataType;
struct ListNode{
ListNode(const DataType& data = DataType())
: _pNext(0)
, _pPre(0)
, _data(data)
{}
ListNode* _pNext;
ListNode* _pPre;
DataType _data;
};
class MyList
{
public:
//构造空MyList
MyList()
{
CreateHead();
}
//MyList有n个值为data的结点
MyList(size_t n, const DataType& data)
{
CreateHead();
for (size_t i = 0; i < n; ++i)
PushBack(data);
}
//拷贝构造
MyList(const MyList& list)
{
_pHead = new ListNode();
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
ListNode* pNode = list._pHead->_pNext;
while (pNode != list._pHead){
this->PushBack(pNode->_data);
pNode = pNode->_pNext;
}
}
//用[firts,last]区间构造MyList
MyList(DataType* first, DataType* last)
{
CreateHead();
while (first != last){
PushBack(*first++);
}
}
//赋值运算符重载
MyList& operator=(const MyList& list)
{
if (this != &list){
this->Clear();
ListNode* pNode = list._pHead->_pNext;
while (pNode != list._pHead){
this->PushBack(pNode->_data);
pNode = pNode->_pNext;
}
}
return *this;
}
//析构函数
~MyList()
{
Clear();
DestroyHead();
}
//获取链表的大小
size_t Size()const
{
size_t count = 0;
ListNode* pNode = _pHead->_pNext;
while (pNode != _pHead){
count++;
pNode = pNode->_pNext;
}
return count;
}
//判断链表是否为空
bool Empty()const
{
return _pHead->_pNext == _pHead;
}
//重置链表的大小
void ReSize(size_t newSize, const DataType& data = DataType())
{
size_t oldSize = Size();
if (newSize <= oldSize){
for (size_t i = newSize; i < oldSize; ++i)
PopBack();
}
else{
for (size_t i = oldSize; i < newSize; ++i)
PushBack(data);
}
}
//获取链表的第一个结点
DataType& Front()
{
return _pHead->_pNext->_data;
}
const DataType& Front()const
{
return _pHead->_pNext->_data;
}
//获取链表的最后一个结点
DataType& Back()
{
return _pHead->_pPre->_data;
}
const DataType& Back()const
{
return _pHead->_pPre->_data;
}
//尾插
void PushBack(const DataType& data)
{
ListNode* pNewNode = new ListNode(data);
pNewNode->_pPre = _pHead->_pPre;
pNewNode->_pNext = _pHead;
_pHead->_pPre = pNewNode;
pNewNode->_pPre->_pNext = pNewNode;
}
//尾删
void PopBack()
{
ListNode* pNode = _pHead->_pNext;
if (pNode != _pHead){
_pHead->_pPre = pNode->_pPre;
pNode->_pPre->_pNext = _pHead;
delete pNode;
}
}
//头插
void PushFront(const DataType& data)
{
ListNode* pNewNode = new ListNode(data);
pNewNode->_pPre = _pHead;
pNewNode->_pNext = _pHead->_pNext;
_pHead->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
}
//头删
void PopFront()
{
ListNode* pNode = _pHead->_pNext;
if (pNode != _pHead){
pNode->_pNext->_pPre = _pHead;
_pHead->_pNext = pNode->_pNext;
delete pNode;
}
}
//给出指定位置插入
void Insert(ListNode* pos, const DataType& data)
{
ListNode* pNewNode = new ListNode(data);
pNewNode->_pPre = pos->_pPre;
pNewNode->_pNext = pos;
pNewNode->_pPre->_pNext = pNewNode;
}
//给出指定位置删除
void Erase(ListNode* pos)
{
if (pos){
pos->_pPre->_pNext = pos->_pNext;
pos->_pNext->_pPre = pos->_pPre;
delete pos;
}
}
//清空
void Clear()
{
ListNode* pNode = _pHead->_pNext;
while (pNode != _pHead){
_pHead->_pNext = pNode->_pNext;
delete pNode;
pNode = pNode->_pNext;
}
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
//查找
ListNode* Find(const DataType& data)
{
ListNode* pNode = _pHead->_pNext;
while (pNode != _pHead){
if (pNode->_data == data){
return pNode;
pNode = pNode->_pNext;
}
}
return nullptr;
}
private:
//我们这个双向循环链表是带头结点的,所以要给出创建头结点的函数
void CreateHead()
{
_pHead = new ListNode;
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
//销毁函数
void DestroyHead()
{
delete _pHead;
_pHead = 0;
}
friend ostream& operator<<(ostream& _cout, const MyList& list)
{
ListNode* pNode = list._pHead->_pNext;
while (pNode != list._pHead){
cout <<pNode->_data << " ";
pNode = pNode->_pNext;
}
return _cout;
}
private:
ListNode* _pHead;
};
void Test()
{
MyList list1;
MyList list2(10, 5);
cout << list1 << endl;
cout << list2 << endl;
list1 = list2;
cout << list1 << endl;
list1.PushBack(3);
list1.PushBack(4);
list1.PushBack(5);
list1.PushBack(6);
list1.PushBack(7);
cout << list1 << endl;
list2.PushBack(6);
list2.PushBack(7);
list2.PushBack(8);
list2.PushBack(9);
list2.PushBack(0);
cout << list2 << endl;
list1.PopBack();
list1.PopBack();
cout << list1 << endl;
list1.PushFront(11);
cout << list1 << endl;
list2.PopBack();
list2.PopBack();
cout << list2 << endl;
list2.PushFront(12);
cout << list2 << endl;
ListNode* pos;
pos = list1.Find(4);
list1.Insert(pos, 8);
cout << list1 << endl;
list1.Erase(pos);
cout << list1 << endl;
pos = list2.Find(4);
list2.Insert(pos, 8);
cout << list2 << endl;
list2.Erase(pos);
cout << list2 << endl;
list1.ReSize(10, 3);
cout << list1 << endl;
list2.ReSize(20, 6);
cout << list2 << endl;
list1.Front();
list1.Back();
list2.Front();
list2.Back();
}
int main()
{
Test();
return 0;
}
运行结果: