C++自己实现list

 

 C++自己实现list

  前两个博客发表了自己写的stack(栈)和queue(队列),感觉比较简单,今天想试着实现list,结果发现,不是那么容易,感觉自己对STL的底层不是很了解,

真要自己实现还真的很难,看STL的源代码,那个晕啊...那代码也写得太难理解了,当然跟我不了解有关,但我相信,在将来的某一天我会懂的,你看我的代码也会懂的。

  话说:STL中的list的内部结构就是一个双向链表,这个东东以前还真没有玩过,就凭他用的是双向链表我就不想用他,指针太多,耗资源,当然存在就有他的价值,

他能快速访问其中的元素。 废话总该少说,代码就该多些。

  有那么一点高兴的是实现双向链表的翻转,其他的没什么了,list还没有实现,由于现在能力有限,新的版本一定会发布的,你就将就着看吧!

#include <iostream>
using namespace std;

template<typename T>
class list 
{
	public :
		list()
		{
			initialize();
		}

		list(int count)
		{
			initialize();
			if(count>0)
			{
				for(int i=0;i<count;i++)
				{
					push_front(0);
				}
			}
		}

		list(int count,T data)
		{
			initialize();
			if(count>0)
			{
				for(int i=0;i<count;i++)
				{
					push_front(data);
				}
			}
		}

		//显示最后一个节点
		T& back()
		{
			checkEmpty();
			return cur->data;
		}

		T& back() const
		{
			return back();
		}

		//显示第一个节点
		T& front()
		{
			checkEmpty();
			return head->next->data;
		}

		T& front() const
		{
			return front();
		}

		//弹出最后一个节点
		void pop_back()
		{
			checkEmpty();
			cur=cur->prev;
			delete cur->next;
			cur->next=NULL;
			--len;
		}

		//弹出第一个节点
		void pop_front()
		{
			checkEmpty();
			node* tmp=head->next;
			head->next=tmp->next;
			tmp->prev=head;
			delete tmp;
			--len;
		}

		//前插节点
		void push_front(const T& t)
		{
			node* newNode=new node(t);
			head->next=newNode;
			newNode->prev=head;
			++len;
		}

		//后插节点
		void push_back(const T& t)
		{
			node* newNode=new node(t);
			newNode->prev=cur;
			cur->next=newNode;
			cur=newNode;
			++len;
		}
 
		//删除所有值为t的节点
		void remove(const T& t)
		{
			checkEmpty();
			node* tmp=head->next;
			for(int i=0;i<len;i++)
			{
				if(tmp->data!=t)
				{
					tmp=tmp->next;
					continue;
				}
				 
				if(tmp->next==NULL)//删除最后一个节点
				{
					cur=tmp->prev; //将当前节点指向最后一个节点的前一个节点
					cur->next=NULL;//由于保持当前节点指向最后一个节点,他的下一个节点当然为空
				}else //删除中间节点
				{
					tmp->prev->next=tmp->next; //要删除节点的前一个节点的next指针指向要删除节点的下一个节点
					tmp->next->prev=tmp->prev; //要删除节点的下一个节点的prev指针指向要删除节点的前一个节点
				}
				--len;
				node* t=tmp->next;
				delete tmp;
				tmp=t;
			}
		}
 

		 //反转链表
		 //每次都修改当前节点的前后节点指针
		 //最后一个节点的下一个指针指向前一个节点
		 void reverse()
		 {
			checkEmpty();
			
			node* prev = head;// 上一个节点
			node* pcur = head->next;//当前节点
			node* next;
			while (pcur !=NULL)
			{
				if(!pcur->next)
				{
					pcur->next=prev;//最后一个节点的下一个节点指向前一个节点
					break;
				}

				next = pcur->next; //下一个节点
				 
				pcur->next=prev;  //修改当前节点的下一个节点
				pcur->prev=next;  //修改当前及诶单的上一个节点

				prev=pcur;        //将当前节点设为上一个节点
				pcur=next;        //将下一个节点设为当前节点
			}
			cur=head->next;       //末节点指向头节点
			head->next=pcur;      //头指针指向当前节点,也就是指向翻转之前的末节点
		 }

		 //排序
		 //节点之间直接交换数据,而没有用修改指针指向
		 void sort()
		 {
			 if(empty())
			 {
				return;
			 }
			 node *p,*t;
			 p=head->next;
			 T d;
			 while(p!=NULL)
			 {
				 t=p;
				while(t!=NULL)
				{
					if(p->data>t->data)
					{
						d=p->data;
						p->data=t->data;
						t->data=d;
					}
					t=t->next;
				}
				p=p->next;
			 }
		 }


		//链表元素个数
		int size()
		{
			return len;
		}

		void resize(int count)
		{
			resize(count,0);
		}

		//重新设置元素
		void resize(int count,T t)
		{
			if(count<0)
			{
				throw new exception("元素的个数不能小于0!");
			}
			clear();  //内存是必须释放的    
			while(count--)
			{
				push_front(t);
			}
		}

		//清空集合
		void clear()
		{
			if(empty())
			{
				return;
			}
			node *tmp=head;
			node *t=tmp->next;
			while(t!=NULL)
			{
				tmp=t;
				t=t->next;
				delete tmp;
			}
			tmp=NULL;
			t=NULL;

			cur=head;//当前节点指向头指针
		}
 

		//链表是否为空
		bool empty() const
		{
			return len==0;
		}

		//判断链表是否为空
		void checkEmpty()
		{
			if(empty())
			{
				throw new exception("集合中没有元素!");
			}
		}


	private :
		typedef struct node1
		{
			node1 *prev,*next;
			T  data;
			node1(T t):data(t),prev(NULL),next(NULL){}
		}node;

		node* head;//头节点
		node* cur; //当前节点,指向末节点
		int len;   //节点个数

        void initialize()
		{
			cur=head=new node(-1);
			len=0;
		}
};


作者:陈太汉

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值