码迷,mamicode.com
首页 > 编程语言 > 详细

【C++】双向链表

时间:2015-08-31 17:26:28      阅读:259      评论:0      收藏:0      [点我收藏+]

标签:

     博客介绍了C语言,以及C++的单向链表。那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针。双向链表相比较单向链表,主要有下面几个特点:

    (1)在数据结构中具有双向指针

    (2)插入数据的时候需要考虑前后的方向的操作

    (3)同样,删除数据的是有也需要考虑前后方向的操作

    那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下:


源代码:

#include <iostream>
using namespace std;

typedef int DataType;

class LinkNode
{
	friend class List;
public:
	LinkNode(const DataType& x)
		:_data(x)
		,_next(NULL)
		,_prev(NULL)
	{}
	~LinkNode()
	{

	}
protected:
	DataType _data;		// 数据
private:
	LinkNode* _prev;	// 前驱
	LinkNode* _next;	// 后继
};

class List
{
public:
	List()
		:_head(NULL)
		,_tail(NULL)
	{}
	~List()					
	{}
	List(const List& l)
	{}
	List& operator=(const List& l);

public:
	void Print()
	{
		LinkNode *begin=_head;
		while (begin)
		{
			cout<<begin->_data<<"->";
			begin=begin->_next;

		}
		cout<<"NULL"<<endl;
	}

	void PushBack(const DataType& x)
	{
		// 1.空链表
		// 2.一个或以上节点
		if(_head == NULL)
		{
			_head=new LinkNode(x);
			_tail=_head;
		}
		else
		{
			_tail->_next=new LinkNode(x);
			_tail->_next->_prev=_tail;
			_tail=_tail->_next;
		}
	}

	void PopBack()
	{
		// 1.空链表
		// 2.一个节点
		// 3.两个及以上节点
		if (_head ==NULL)
		{
			return ;
		}

		if (_head == _tail)
		{
			delete _head;
			_head = NULL;
			_tail = NULL;
		}
		else
		{
			LinkNode* del=_tail;
			_tail=_tail->_prev;
			_tail->_next=NULL;
			//_tail->_prev=_tail->_prev;		此句功能包含在_tail=_tail->_prev;中!!
			delete del;

			/*tail=_tail->_prev;
			delete _tail->_next;
			_tail->_next=NULL;*/
		}
	}

	void PushFront(const DataType& x)
	{
		//1.空链表
		//2.非空链表
		if(_head == NULL)
		{
			_head=new LinkNode(x);
			_tail=_head;
		}

		else
		{
			LinkNode *tmp = new LinkNode(x);
			tmp->_next=_head;
			_head->_prev=tmp;
			tmp->_prev = NULL;
			_head=tmp;

		}
	}

	void PopFront()
	{
		// 1.空链表
		// 2.一个节点
		// 3.两个及以上节点
		if (_head == NULL)
		{
			return ;
		}

		if (_head == _tail)
		{
			delete _head;
			_head = NULL;
			_tail = NULL;
		}

		if(_head != _tail)			//链表清空之后的判断,否则出现内存访问冲突
		{
			LinkNode *del =(_head);
			_head=_head->_next;
			_head->_prev=NULL;
			delete del;
		}
	}

	//插入
	void Insert(LinkNode* pos, const DataType& x)
	{
		// 1.空链表
		// 2.尾部插入
		// 3.中间插入
		if (_head == NULL)
		{
			_head=new LinkNode(x);
			_tail=_head;
		}

		if(pos == _tail)
		{
			PushBack(x);
		}
		else
		{
			LinkNode *tmp=new LinkNode(x);
			pos->_prev->_next=tmp;		
			pos->_next->_prev=tmp;

			tmp->_prev=pos->_prev;
			tmp->_next=pos->_next;
		}

	}
		
	//查找
	LinkNode* Find(const DataType& x)
	{
		if (_head == NULL)
		{
			return NULL;
		}
		
		LinkNode* begin = _head;
		while(begin != NULL)
		{
			if(begin->_data == x)
			{
				return begin;
			}
			else
			{
				begin = begin->_next ;
			}
		}
		return NULL;
		cout<<"没有找到该节点"<<endl;
	}

	//删除
	void Erase(LinkNode* del)
	{
		//1.空链表
		if(_head == NULL)
		{
			return ;
		}
		else 
		{
			//2.一个节点且是删除节点
			if ((_head == _tail) && (_head == del))
			{
				delete _head;
				_head=NULL;
				_tail=NULL;
			}
			
			else 
			{//3.多个节点
					//del为头
				if (_head == del)
				{
					PopFront();
					/*_head=_head->_next;
					_head->_prev=NULL;
					delete _head->_prev;*/
				}
				else
				{
					//del在尾
					if(del == _tail)
					{
						PopBack();
						/*del->_prev->_next=NULL;
						_tail=del->_prev;
						delete del;*/
					}
					//del在中
					else
					{
						del->_prev->_next=del->_next;
						del->_next->_prev=del->_prev;
						delete del;
					}	
				}
			}
		}
	}
	void remove(DataType * x)
	{
		LinkNode *ret=Find(*x);
		Erase(ret);
	
	}
	//逆置
	void Reverse()
	{
		LinkNode* tmp1 = _head;
		LinkNode* tmp2 = _tail;
		while(tmp1 != tmp2 && tmp2->_next != tmp1) 
		{
			DataType a = tmp1->_data ;
			tmp1->_data = tmp2->_data ;
			tmp2->_data = a;

			tmp1 = tmp1->_next ;
			tmp2 = tmp2->_prev ;
		}
	}

private:
	LinkNode* _head;
	LinkNode* _tail;
};

void Test1()
{
	List l1;
	l1.PushBack(1);
	l1.PushBack(2);
	l1.PushBack(3);
	l1.PushBack(4);
	l1.Print();

	LinkNode* ret = l1.Find(4);
	//cout<<"ret:"<<ret->_data<<endl;	//测试失败“LinkNode::_data”: 无法访问 protected 成员(在“LinkNode”类中声明)	
	//l1.PopBack();
	//l1.PopBack();
	//l1.PopBack();
	//l1.PopBack();
	//l1.PopBack();

	//l1.Insert(s,3);
	//l1.PopFront();
	//l1.PopFront();
	//l1.PopFront();
	//l1.PopFront();
	//l1.PopFront();

	/*l1.PushFront(0);
	l1.Print();*/

	//l1.Erase(ret);
	//l1.Reverse();
	/*DataType x=3;
	l1.remove(&x);*/
	l1.Print();
}

void Test2()
{
	List l1;
	l1.PushFront(1);
	l1.PushFront(2);
	l1.PushFront(3);
	l1.PushFront(4);
	l1.Print();

	l1.PopFront();
	l1.PopFront();
	l1.PopFront();
	l1.PopFront();
	l1.PopFront();
	l1.Print();
}

int main()
{
	Test1();
	//Test2();
getchar();
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

【C++】双向链表

标签:

原文地址:http://blog.csdn.net/zhangchaoq/article/details/48135799

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!