因为数据结构的代码没有最好,只有更好,因此在文章后面加个版本号记录一下自己的代码变化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;
}