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

来源:互联网 发布:淘宝达人大v账号购买 编辑:程序博客网 时间:2024/06/17 12:26

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

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



阅读全文
0 0