【c++】实现双向链表List类及测试

#include <iostream>
using namespace std;

// 数据类型
typedef  int DataType;

// 定义节点
struct Node
{
	// 构造函数
	Node(DataType data = 0)
		:my_data(data)
		,pPre(NULL)
		,pNext(NULL)
	{}
	DataType my_data;  // 结点数据
	Node* pPre;		   // 指向前一个节点的指针 
	Node* pNext;	   // 指向下一个节点的指针
};


// 双向链表类
class List
{
private:
	Node* pHead;  // 头指针
	Node* pTail;  // 尾指针
	size_t size;  // 当前元素个数
	
public:
	// 构造函数
	List()
		:pHead(NULL)
		,pTail(NULL)
		,size(0)
	{}

	// 拷贝构造函数
	List(const List &list)
		:pHead(NULL)
		,pTail(NULL)
		,size(0)
	{
		Node *tempNode = list.pHead;
		for(size_t i = 0; i < list.size; i++)
		{

			PushBack(tempNode->my_data);
			tempNode = tempNode->pNext;
		}

	}

	// 赋值运算符重载
	List& operator=(const List &l)
	{
		if (this->pHead != l.pHead)  // 判断是否是自己给自己赋值
		{
			Node* tempNode = l.pHead; 
			if (NULL != pHead)
			{
				Clear();				// 释放掉原来的空间
			}
			for (size_t i = 0; i < l.size; i++) // 插入元素
			{
				PushBack(tempNode->my_data);
				tempNode = tempNode->pNext;
			}
		}
		return *this;
	}

	~List()
	{
		Clear();
	}
	
	// 清空链表
	void Clear()
	{
		Node *curNode = this->pHead;
		Node *curNext = this->pHead;
		while (curNext)
		{
			curNext = curNext->pNext;
			delete curNode;
			curNode = curNext;
		}
		pTail = pHead = NULL;
		size = 0;
	}

	// 尾插
	void PushBack(const DataType &value)
	{
		// 链表为空时  
		if (this->size == 0)
		{
			pHead = pTail =  BuyNode(value);
		}
		else  // 不为空时
		{
			Node * tempNode = BuyNode(value);
			pTail->pNext = tempNode;
			tempNode->pPre = pTail;
			pTail = tempNode;
		}
		++size;
	}

	// 尾删
	void PopBack()
	{
		// 为空时
		if (0 == this->size)
		{
			return;
		} // 只有一个节点时
		else if(1 == this->size)
		{
			delete pHead;
			pHead = pTail = NULL;
			size = 0;
		}  // 多个节点
		else
		{
			pTail = pTail->pPre;
			delete pTail->pNext;
			pTail->pNext = NULL;
			--size;
		}
	}

	 // 头插
	void PushFront(const DataType &value)
	{
		if (0 == this->size)
		{
			pHead = pTail = BuyNode(value);
		}
		else
		{
			Node *newNode = BuyNode(value);
			newNode->pNext = pHead;
			pHead->pPre = newNode;
			pHead = newNode;
		}
		++size;
	}

	// 头删
	void PopFront()
	{
		if (0 == this->size)
		{
			return;
		}
		else if (1 == this->size)
		{
			delete pHead;
			pHead = pTail = NULL;
			--size;
		} 
		else
		{
			pHead = pHead->pNext;
			delete pHead->pPre;
			pHead->pPre = NULL;
			--size;
		}
	}

	// 查找一个元素 存在返回节点 不存在返回null
	Node* Find(const DataType &value)const
	{
		Node * tempNode = this->pHead;
		while (tempNode)
		{
			if (value == tempNode->my_data)
			{
				return tempNode;
			}
			tempNode = tempNode->pNext;
		}
		return NULL;
	}

	// 给的位置插入一个节点
	void Insert(Node* pos, const DataType &value)
	{
		// 拦截位置为空
		if (NULL == pos)
		{
			return;
		} // 位置尾节点时
		else if(pos == this->pTail)
		{
			PushBack(value);
		}
		else
		{
			// 默认插入到给定位置后面
			Node* tempNode = BuyNode(value);
			tempNode->pNext = pos->pNext;
			pos->pNext->pPre = tempNode;
			tempNode->pPre = pos;
			pos->pNext = tempNode;
			++size;
		}
	}

	// 删除一个节点
	void Erase(Node *pos)
	{
		// 位置为空 时候
		if ( NULL == pos)
		{
			return;
		}
		else if(pos == this->pTail)  // 分别处理头和尾节点是因为 多个节点处理的时候会用到前后两个位置 也就是大于等于3个结点的情况
		{
			PopBack();
		}
		else if (pos == this->pHead)
		{
			PopFront();
		}
		else
		{
			pos->pNext->pPre = pos->pPre;
			pos->pPre->pNext = pos->pNext;
			delete pos;
			pos = NULL;
			--size;
		}
	}

	// 判断是否为空
	bool Empty()const
	{
		return 0 == this->size;
	}

	// 返回节点个数
	size_t Size()const
	{
		return this->size;
	}

	//返回第一个结点元素
	Node& Front()
	{
		return *pHead;
	}
	const Node& Front()const
	{
		return *pHead;
	}
	//返回第一个结点元素
	Node& Back()
	{
		return *pTail;
	}
	const Node& Back()const
	{
		return *pTail;
	}
private:
	Node* BuyNode(const DataType &value)const
	{
		return new Node(value);
	}

};

int main()
{
	List   testList;

	// 测试尾插
	testList.PushBack(1);
	testList.PushBack(2);
	testList.PushBack(3);
	// 测试返回头结点
//	cout<< testList.Front().my_data << endl;
	// 测试返回尾结点
//	cout << testList.Back().my_data << endl;
	// 测试元素个数
// 	cout << testList.Size() << endl;
//  测试是否为空
//	cout << testList.Empty() << endl;
	// 测试删除元素
// 	testList.Erase(testList.Find(1));
// 	testList.Erase(testList.Find(2));
// 	testList.Erase(testList.Find(3));
// 	testList.Erase(testList.Find(8));

	// 测试插入节点
	testList.Insert(testList.Find(3), 9);
// 	testList.Insert(testList.Find(1), 8);

	// 测试查找元素
// 	cout << testList.Find(8) << endl;
// 	cout << testList.Find(1) << endl;
	// 测试头删
// 	testList.PopFront();
// 	testList.PopFront();
// 	testList.PopFront();
// 	testList.PopFront();
	// 测试头插
// 	testList.PushFront(0);
// 	testList.PushFront(-1);
// 	testList.PushFront(-2);
	
	// 测试尾删
// 	testList.PopBack();
// 	testList.PopBack();
// 	testList.PopBack();
	// 测试拷贝构造函数
// 	List   l2(testList);
// 	l2.PushBack(4);
// 	l2.PushBack(5);
	// 测试赋值运算符重载
//	l2 = testList;


	
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值