C++实现双向链表

wKioL1busLOTWsqhAAAI3EcuKqo751.pngList.h

//
///  这里建立两个类,一个节点类和一个List类,与单链表不同的是双向链表的节点要多一
//   个前驱指针,相应的,双向链表函数实现要与单链表实现有所差异

	typedef int DataType;

	//struct LinkNode     //节点类(复合形态)
	//{
	//	friend class SList;
	              //将SList设为友元,便于SList类可以访问节点类的私有成员
	//public:
	//	LinkNode(const DataType x);	
	//private:
	//	DataType _data;    //节点的数据
	//	LinkNode* _next;    //指向该节点的下一个节点
	//      LinkNode* _prev;    //指向该节点的前一个节点
	//};

	//直接用struct定义LinkNode类,因为struct的成员默认为公有数据成员,所以可直接访问
	struct LinkNode      //节点类(建议写法)
	{
		LinkNode(const DataType x);
		DataType _data;    //节点的数据
		LinkNode* _next;    //后继指针
		LinkNode* _prev;      //前驱指针
	};

	class List    //链表类
	{
	public:
		List();         //构造函数
		List(const List& s);        //拷贝构造
		List &operator=(List& s);    //赋值运算符的重载
		~List();

	public:
		void Reverse();
		void Swap(List& s);
		void PrintSList();   //打印链表
		void PushBack(const DataType& x);    //在尾部插入一个节点
		void Clear();         //链表置空
		void PopBack();
		void PushFront(DataType x);  //头插
		void PopFront();    //删除首节点
		void Insert(LinkNode* pos, DataType x);//固定位置插入一个节点
		void Erase(LinkNode* pos);        //删除某一节点
		LinkNode* Find(DataType x);       //查找节点并返回这个节点的地址
		int Amount();   //计算链表节点的数目
		void Remove(DataType x);     //查找某节点并删除

	private:
		LinkNode* _head;    //指向头结点
		LinkNode* _tail;    //指向尾节点
	};

List.cpp

	#include<iostream>
	using namespace std;
	#include<assert.h>
	#include"List.h"

	//节点类构造函数*
	LinkNode::LinkNode(const DataType x)
	:_data(x)
	, _next(NULL)
	, _prev(NULL)
	{}

	//链表类*
	List::List()         //构造函数
	: _head(NULL)
	, _tail(NULL)
	{}
	
	List::List(const List& s)          //拷贝构造
	: _head(NULL)
	, _tail(NULL)
	{
		if (s._head == NULL)
		{
			return;
		}
		LinkNode* tmp = s._head;
		while (tmp)
		{
			PushBack(tmp->_data);
			tmp = tmp->_next;
		} 

	}
	
	//赋值运算符的重载(传统方法)
	//SList & SList::operator=(const SList& s)    
	//{
	//	if (this != &s)
	//	{
	//		_head = NULL;
	//		_tail = NULL;
	//		LinkNode* tmp = s._head;
	//	do{
	//		PushBack(tmp->_data);
	//		tmp = tmp->_next;
	//	     } while (tmp != s._head);
	//	}
	//	return *this;	
	//}

	//赋值运算符的重载(高效写法)*
	/*void SList::Swap(SList& s)
	{
	swap(_head, s._head);
	swap(_tail, s._tail);

	}
	SList&  SList::operator=(SList &s)
	{
	if (this != &s)
	{
	SList tmp(s);
	Swap(tmp);
	}
	return *this;
	}*/

	List&  List::operator=(List &s)     //赋值运算符的重载再优化(推荐写法)
	{
		if (this != &s)
		{
			swap(_head, s._head);
			swap(_tail, s._tail);
		}
		return *this;
	}
	List::~List()    //析构
	{
		Clear();
	}

	void List::Reverse()   //链表逆置(利用头插新节点的方法)
	{
		if (_head == NULL || _head== _tail)
		{
			return;
		}
		int ret = Amount();

	/*  //  方法一(相当于用头插的方式重新建立链表)
   	_tail = new LinkNode(_head->_data);
		LinkNode* begin = NULL;
		LinkNode* tmp = _tail;
		while (--ret)
		{
			LinkNode* del = _head;
			_head = _head->_next;
			delete del;			
			begin = new LinkNode(_head->_data);
			begin->_next = tmp;
			tmp->_prev = begin;
			tmp = begin;
		}
		_head = begin;*/

	//  方法二(只是交换对称位置节点的数据)**(高效)
		LinkNode* begin = _head;
		LinkNode* end = _tail;
		while (ret)
		{
			if (end->_next == begin)
				break;
			ret /= 2;
			swap(begin->_data, end->_data);
			begin = begin->_next;
			end = end->_prev;
		}
	
		 /*// 方法三  交换前驱和后继指针
		  swap(_head, _tail);
		  LinkNode* cur = _head;
		  while (cur)
		  {
		      swap(cur->_prev,cur->_next);
		      cur = cur->_next;
		  }
		  */
		
	}

	//打印链表*
	void List::PrintSList()
	{
		//头结点为空时,无需打印链表
		if (_head == NULL)
		{
			cout << "This SList is Empty !" << endl;
			return;
		}
		else
		{
			LinkNode* tmp = _head;	
		   while (tmp)
		   {
				cout << tmp->_data << "-->";
				tmp = tmp->_next;
			} 
			cout <<"NULL"<< endl;
		}
	}
	
	void List::PushBack(const DataType& x)    //在尾部插入一个节点*
	{
		//如果链表为空,插入节点后只有一个节点,此时_head=_tail
		if (_head == NULL)
		{
			_head = new LinkNode(x);
			_tail = _head;
		}
		else
		{
			_tail->_next = new LinkNode(x);
		    _tail->_next->_prev=_tail;
			_tail = _tail->_next;
		}
	}
	
	void List::Clear()         //链表置空*
	{
		LinkNode* begin = _head;
		while (begin != _tail)
		{
			_head = _head->_next;
			delete begin;
			begin = _head;
		}
		_head = NULL;
		_tail = NULL;
	}
	
	void List::PopBack()    //尾删
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
		}
		else if (_head == _tail)
		{
			delete _head;
			_head = NULL;
			_tail = NULL;
		}
		else
		{
			LinkNode* cur = _head;
			while (cur->_next != _tail)
			{
				cur = cur->_next;
			}
			delete _tail;
			_tail = cur;
			_tail->_prev = cur->_prev;
			_tail->_next = NULL;
		}
	}
	
	void List::PushFront(DataType x)  //头插*
	{
		if (_head == NULL)
		{
			PushBack(x);
		}
		else
		{
			LinkNode* tmp = _head;
			_head = new LinkNode(x);
			_head->_next = tmp;
			tmp->_prev = _head;
		}
	}
	
	void List::PopFront()    //删除首节点
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
			return;
		}
		LinkNode* tmp = _head;
		_head = _head->_next;
		_head->_prev = NULL;
		delete tmp;
	}

	//固定位置插入一个节点(这个函数需和Find函数搭配使用)
	//先用Find函数找到新节点需要插入的位置
	//(将Find函数的返回值传给Insert函数的参数pos),再在pos节点后面插入新节点x
	void List::Insert(LinkNode* pos, DataType x)   //*
	{
		assert(pos);
		if (pos == _tail)
		{
			PushBack(x);
		}
		else
		{
			LinkNode* tmp = new LinkNode(x);
			tmp->_next = pos->_next;
			pos->_next = tmp;
			tmp->_next->_prev = tmp;
			tmp->_prev = pos;
		}
	}
	
        //删除某一节点,同样,要先找到该节点并传参给Erase函数
	void List::Erase(LinkNode* pos)        
	{
		assert(pos);
		if (pos == _tail)
		{
			PopBack();
		}
		else if (pos == _head)
		{
			PopFront();
		}
		else
		{
			pos->_prev->_next = pos->_next;
			pos->_next->_prev = pos->_prev;
			delete pos;
		}
	}
	
	//查找节点并返回这个节点的地址
	LinkNode* List::Find(DataType x)       
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
			return NULL;
		}
		else
		{
			LinkNode* tmp = _head;
			while (tmp != NULL)
			{
				if (tmp->_data == x)
				{
					return tmp;
				}
				tmp = tmp->_next;
			} 
			return NULL;
		}
	}
	
	int List::Amount()   //计算链表节点的数目
	{
		if (_head == NULL)
		{
			return 0;
		}
		else
		{
			int count = 0;
			LinkNode* cur = _head;
			while (cur != _tail)
			{
				count++;
				cur = cur->_next;
			}
			return ++count;
		}
	}
	
	void List::Remove(DataType x)      //查找某节点并删除
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
		}
		else
		{
			LinkNode* tmp = Find(x);
			if (tmp != NULL)
			{
				Erase(tmp);
			}
		}
	}

用例测试(Test.cpp)

	#include"List.h"
	#include<stdlib.h>
#include<iostream>
using namespace std;

	void Test1()
	{
		List list1;
		list1.PushBack(1);
		list1.PushBack(2);
		list1.PushBack(3);
		list1.PushBack(4);
		list1.PushBack(5);
		list1.PushBack(6);
		list1.PrintSList();

	/*	List list2(list1);
		list2.PrintSList();*/

		List list2=list1;
		list2.PrintSList();
		//list2.PopBack();
		//list2.Clear();
		//list2.PushFront(0);
		//list2.PopFront();

		//检验Find函数
		LinkNode* ret=list2.Find(4);
		if (ret != NULL)
		{
			cout << "ret:" << ret << " " << ret->_data << endl;
		}
		else
		{
			cout << "Not exit !" << endl;
		}
		
	/*	int ret=list2.Amount();
		cout << ret << endl;*/

		//list2.Erase(list2.Find(5));
		//list2.Insert(list2.Find(2), 0);
		//list2.Remove(3);
		list2.Reverse();
		list2.PrintSList();
	}

	int main()
	{
		Test1();
		system("pause");
	}



本文出自 “言安阳” 博客,谢绝转载!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值