C++实现MyList

上篇文章我们用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;
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值