自己基于指针实现单链表(1.0)(shaffer教材)(2.0)

因为数据结构的代码没有最好,只有更好,因此在文章后面加个版本号记录一下自己的代码变化hh。


基于单链表实现线性表我们有几个点需要注意一下:

1、curr的位置应该是“我们想象的”当前位置的前一个位置

举例子:

1,2,3,4,5,我们如果想在3插入位置,那么curr就应该设定在2

如果我们设定在3,那么我们就无法找到3的前驱2来修改它的后继。

有补救方法,记录当前是第几个节点,然后从头遍历,但是这样子十分麻烦,因此我们设定当前位置为2。


如何理解插入呢?我们可以理解为,插入就是,插入的元素成为“想象中的当前位置”的那个位置

eg

1,2,3,4,5

我们想在3插入8

然后当前位置设定为2,最后操作

1,2,8,3,4,5

8取代了原先3的位置,这样子比较好理解。


2、如何理解tail呢?

如果我们有了解后面的双向链表,它的tail是一个无实际含义,为了排除特殊情况而设的节点。

那么我们在单链表仍然有必要这样子设定吗?答案:没有

我之前一直有这样子的误解,那就是,如何在尾部“insert”一个新的元素啊?

我们要明确一个根本,那就是

我们的curr是真正的curr-1。

如果我们的curr是真正的curr,那么我们就需要无实际内涵的tail,但是现在我们的curr是真正的curr-1,所以说,我们并不需要这个无实际内涵的tail,tail可以直接指向我们的最后一个元素。


代码:

#include<iostream>
using namespace std;

template<typename E>
class node
{
	public:
		E data;
		node<E>* next;

		node(E d,node<E>*n=NULL)
		{
			data=d;
			next=n;
		}
		node(node<E>*n=NULL)
		{
			next=n;
		}
};

template<typename E>
class LList
{
	private:
		node<E>*head;
		node<E>*curr;
		node<E>*tail;
		int size;
	void init()
	{
		head=new node<E>();
		curr=head;
		tail=head;
		size=0;
	}
	void removeall()
	{
		while(head!=NULL)
		{
			curr=head;
			head=head->next;
			delete curr;
			curr=NULL;
		}
	}
	public:
		LList()
		{
			init();
		}
		~LList()
		{
			removeall();
		}
		void clear()
		{
			removeall();
			init();
		}
		void insert(E elem)
		{
			node <E>*p=new node<E>(elem,curr->next);
			curr->next=p;
			if(curr==tail)
			tail=curr->next;
			size++;
		}
		void append(E elem)
		{
			node <E>*p=new node<E>(elem);
			tail->next=p;
			tail=tail->next;
			size++;
		}
		bool remove()
		{
			if(size==0)
			{
				cout<<"empty"<<endl;
				return false;
			}
			else
			{	
				node<E>*tmp=curr->next;
				curr->next=curr->next->next;
				delete tmp;
				//tmp=NULL;
				size--;
				return true;
			}
		}
		int length()
		{
			return size;
		}
		bool currVal(E&it)
		{
			it=curr->data;
		}
		void next()
		{
			curr=curr->next;
		}
		bool setPos(int i)
		{
			if(i<0||i>=size)
			{
				cout<<"noway"<<endl;
				return false;
			}
			else
			{
				curr=head;
				i--;
				while(i--)
				{
					curr=curr->next;
				}
				return true;
			}
		}
		bool tran()
		{
			if(size==0)
			{
				cout<<"empty"<<endl;
			}
			else
			{

				curr=head->next;
				while(curr!=NULL)
				{			
					cout<<curr->data<<endl;
					curr=curr->next;
				}
			}
		}
};

我想大家关注一下这段代码

bool remove()
		{
			if(size==0)
			{
				cout<<"empty"<<endl;
				return false;
			}
			else
			{	
				node<E>*tmp=curr->next;
				curr->next=curr->next->next;
				delete tmp;
				//tmp=NULL;
				size--;
				return true;
			}
		}

node<E>*tmp=curr->next;
curr->next=curr->next->next;
delete tmp;

一开始我并没有这样子写,而是

curr->next=curr->next->next;

node<E>*tmp=curr->next;

delete tmp;


这样子程序会报错,这是为什么呢?

首先我们如果按照错误的代码来写,这样子的意思就是说

修改了curr的后继,然后把后继删除了。

这并不是我们想要的,我们想要删除的,是修改后继之前的curr的后继。


这是一个小point


//2017.11.2修改

修改如下:

1、当前位置的值应该是curr->next->data

2、next()应该判断一下当前是不是已经是链表的末尾了

bool next()
		{
			if(curr->next==NULL)
			{
				cout<<"last"<<endl;
				return false;
			}
			else
			curr=curr->next;
			return true;
		}

		bool currVal(E&it)
		{
			it=curr->next->data;
		}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值