数据结构—链表List

昨天写了vector之后写了链表,但是没有时间更新,今天补上。

链表是基本的数据结构之一,刚学过语言,没有学过数据结构的同学看上去可能有点吃力,因为又牵扯指针,来回指向,比较容易乱,只要记住一点 指针指向的是一个节点,自己理解了,你就觉得很容易了。

先说一下优缺点吧:

1、在我看来链表就是为了弥补数组插入删除的繁琐操作,而出现的,链表的最大优点就是插入删除节点时的方便。直接删除而不用像数组那样来反复移动元素。

2、链表的缺点就是它开辟了额外的空间来来存数前后节点的指针。


我的作图技术不是很好凑合着看吧,这个图我想说的就是一点(下面介绍)。

我们一般把节点定义成struct;

struct Node
	{
		Object data;//如图的数据
		Node *prev;//这个如图前指针区
		Node *next;//这个如图后指针区
		Node (const Object &d = Object(),Node *p=NULL,Node *q=NULL):data(d),prev(p),next(q){}//这个是构造函数(或者是初试话函数)具体可以查查结构体,没用过也没关系
	};

大家不用担心看不懂,我给大家解释:object是指某个数据类型(如int char等) Node * 是指指向Node的指针 (这个就像 int * 一样) 

我想说明的一点是指针指向的红圆圈里面所有东西的地址。这样就应该好理解了吧。这样看到链表自己画一下就明白了。

下面我们来说实现了。

书中的实现有点费劲,他建立了内部类。这使我们看上去好像很难,其实也就那样,不咸不淡。

跟我一起走。

我尽量每个地方都来加上注释。我们在实现链表时一般加上头结点和为节点来方便操作。

设置私有变量

private:
	struct Node
	{
		Object data;
		Node *prev;
		Node *next;
		Node (const Object &d = Object(),Node *p=NULL,Node *q=NULL):data(d),prev(p),next(q){}
	};
	int thesize;
	Node *head;
	Node *tail;

然后我们来考虑iterator 让我们来实现它 用一个内部类(这些内部类什么的没接触过得听上去搞不懂但是一看就明白了) 迭代器(主要为了遍历元素)

class iterator
	{
	public :
		iterator(){}//构造函数
		Object & operator*()//重载*运算符
		{
			return retrieve();
		}
		const Object & operator *() const//重载*运算符

		{
			return retrieve();
		}
		const iterator &operator++()//重载++
		{
			current = current->next;
			return *this;
		}
		const iterator &operator--()//重载--
		{
			current = current->prev;
			return *this;
		}
		const iterator operator ++(int )//重载++
			iterator old = *this;
			++(*this);
			return old;
		}
		bool operator==(const iterator &rhs)const//重载==
		{
			return current == rhs.current;
		}
		bool operator!=(const iterator &rhs)const//重载!=
		{
			return !(*this==rhs);
		}
	private:
		Node *current;//node的节点指针
		Object & retrieve()const//返回该节点下的数据值
		{
			return current->data;
		}
	protected:
		iterator (Node *p):current(p)	{}//这也是构造函数
		friend class List<Object>;//声明为友元,为了后面再list类中调用;
	};

书中还定义了const_iterator类 ,iterator继承了const_iterator。这里我省略了,直接定义了iterator。


接下来就是我们的LIst类的东西了,类不用说上来肯定是构造函数。

List ()
	{
		init();
	}
	List(const List &rhs)
	{
		init();
		*this = rhs;
	}
	void init()
	{
		thesize = 0;
		head = new Node();
		tail = new Node();
		head->next = tail;
		tail->prev = head;
	}
	~List()
	{
		clear();
		delete head;
		delete tail;
	}
上面就不用说了吧!init()函数下面有实现。

这里重载了= 主要是为了给list赋值。

const List & operator = (const List &rhs)
	{
		if(this==&rhs)
			return *this;
		clear();
		for(iterator it = rhs.begin();it!=rhs.end();it++)
		{
			push_back(*it);
		}
		return *this;
	}


下面是插入删除的操作:

iterator insert(iterator it , const Object &x)//在it的后面插入一个值为x的节点
	{
		Node *p = it.current;
		thesize++;
		return iterator(p->prev = p->prev->next = new Node(x,p->prev,p));
	}
    iterator erase(iterator it)//删除迭代器位置的节点(iterator 就是迭代器 主要为了遍历元素)
	{
		Node *p = it.current;
		iterator retVal=(p->next);
		p->prev->next = p->next;
		p->next->prev = p->prev;
		delete p;
		thesize--;
		return retVal;
	}
	iterator erase(iterator start ,iterator end)//删除迭代器start-end的所有元素
	{
		for(iterator it = start ;it!=end;)
		{
			it=erase(it);
		}
		return end;
	}

下面是基本的方法了 ;

iterator begin()//返回开始第一个节点位置(除头结点)
	{
		return iterator(head->next);
	}
	iterator end()//返回为节点位置
	{
		return iterator(tail);
	}
	int size()const//链表的大小
	{
		return thesize;
	}
	bool empty()const//是否为空
	{
		return size()==0;
	}
	void clear()//清空链表
	{
		while(!empty())
		{
			pop_front();
		}
	}
	Object  front()//返回第一个元素的值
	{
		return *begin();
	}
	Object  back()//返回最后一个元素的值
	{
		return *(--end());
	}
	void push_front(Object &x)//插入前面一个元素
	{
		insert(begin(),x);
	}
	void push_back(Object & x)//插入后面一个元素
	{
		insert(end(),x);
	}
	void pop_front()//删除前面元素
	{
		erase(begin());
	}
	void pop_back()//删除后面元素
	{
		erase(--end());
	}

到这已经基本结束了。

函数实现倒是不复杂。主要是了解这些操作,熟悉链表的用法。

下面是整个代码

#include<iostream> 
using namespace std;
template<typename Object>
class List
{
private:
	struct Node
	{
		Object data;
		Node *prev;
		Node *next;
		Node (const Object &d = Object(),Node *p=NULL,Node *q=NULL):data(d),prev(p),next(q){}
	};
	int thesize;
	Node *head;
	Node *tail;
public:
	class iterator
	{
	public :
		iterator(){}
		Object & operator*()
		{
			return retrieve();
		}
		const Object & operator *() const
		{
			return retrieve();
		}
		const iterator &operator++()
		{
			current = current->next;
			return *this;
		}
		const iterator &operator--()
		{
			current = current->prev;
			return *this;
		}
		const iterator operator ++(int )
		{
			iterator old = *this;
			++(*this);
			return old;
		}
		bool operator==(const iterator &rhs)const
		{
			return current == rhs.current;
		}
		bool operator!=(const iterator &rhs)const
		{
			return !(*this==rhs);
		}
	private:
		Node *current;
		Object & retrieve()const
		{
			return current->data;
		}
	protected:
		iterator (Node *p):current(p)	{}
		friend class List<Object>;
	};
	List ()
	{
		init();
	}
	List(const List &rhs)
	{
		init();
		*this = rhs;
	}
	void init()
	{
		thesize = 0;
		head = new Node();
		tail = new Node();
		head->next = tail;
		tail->prev = head;
	}
	~List()
	{
		clear();
		delete head;
		delete tail;
	}
	const List & operator = (const List &rhs)
	{
		if(this==&rhs)
			return *this;
		clear();
		for(iterator it = rhs.begin();it!=rhs.end();it++)
		{
			push_back(*it);
		}
		return *this;
	}
	iterator insert(iterator it , const Object &x)
	{
		Node *p = it.current;
		thesize++;
		return iterator(p->prev = p->prev->next = new Node(x,p->prev,p));
	}
    iterator erase(iterator it)
	{
		Node *p = it.current;
		iterator retVal=(p->next);
		p->prev->next = p->next;
		p->next->prev = p->prev;
		delete p;
		thesize--;
		return retVal;
	}
	iterator erase(iterator start ,iterator end)
	{
		for(iterator it = start ;it!=end;)
		{
			it=erase(it);
		}
		return end;
	}
	iterator begin()
	{
		return iterator(head->next);
	}
	iterator end()
	{
		return iterator(tail);
	}
	int size()const
	{
		return thesize;
	}
	bool empty()const
	{
		return size()==0;
	}
	void clear()
	{
		while(!empty())
		{
			pop_front();
		}
	}
	Object  front()
	{
		return *begin();
	}
	Object  back()
	{
		return *(--end());
	}
	void push_front(Object &x)
	{
		insert(begin(),x);
	}
	void push_back(Object & x)
	{
		insert(end(),x);
	}
	void pop_front()
	{
		erase(begin());
	}
	void pop_back()
	{
		erase(--end());
	}

};
int main()
{
	
}

c++语言的地方看不懂没关系我们主要是为了熟悉数据结构,具体语言没有要求。

好了!感谢自己坚持。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值