链表:也是一种线性表,跟顺序表相比,每个结点多了个指针域,该指针指向下一个结点。
链表与顺序表的区别
下面就用课室的学生来模拟一下链表与顺序表:假设一个可是有n个学生,每个学生对应一个学号,老师只认识学号1的学生,假设老师要寻找学号i的学生该怎么办呢?
顺序表:所有学生根据学号顺序依次坐,老师只要算一下i-1就能快速找到学号i的学生了。
链表:所有学生随便坐,每个学生知道他学号的下一个人是谁,但不知道其他学号的是谁。老师要查找学号i的同学,只能一个个问,从学号1那里知道学号2,从学号2那里知道学号3,一次类推,直到找到学号i的同学。
看到这里你也许要问了,链表每个结点要花费内存来存储指针不说,查找速度还慢,为什么还要有这种数据结构存在?
增删优势:如果班里转来了一位新同学k,老师想把它安排在i前面,如果是顺序表,那么从学号i到学号n所有人都要往后移动一个位置,如果经常有插班生这可是很恼人的。但如果是链表就不同了,老师只需要告诉学号为i-1的同学,记住以后你后面的就是k同学了,同时告诉k同学以后你后面就是同学i了,这可省事多了吧。同理,如果有个同学转校了,链表也要比顺序表快多了吧
充分利用内存空间:假设一个班有50人,现有一个能容纳百人的课室,但是课室中间有两处桌椅被霸占了,整间课室理论上还能容纳95人,但是没有连续的50个座位了。如果采用顺序表,则只能寻找其他课室了,因为链表不要求按顺序连续做,所以该课室能用,充分利用了零碎内存空间。
单链表的基本实现
创建结构体:
typedef struct LNode{
ElemType data;//结点的值
struct LNode *next;//结点的指针
}LNode,*LinkList;
初始化:
status InitList_L(LinkList &L){
L=new LNode;
L->next=NULL;
return OK;
}
查找:
按顺序查找:
Status GetElem_L(LinkList L,int i,ElemType &e){
LNode p=L->next;
j=1;
while(p&&j<i){
p=p->next;
j++;
}
if(!p||j>i)return error;
e=p->data;
return OK;
}
}
插入:
Status ListInsert(LinkList &L,int i,ElemType &e){
LNode p=L;
int j=0;
while(!p&&j<n-1){
p=p->next;
j++;
}
if(!p||j>i-1)return error;
s=new LNode;
s->data=e;
s->next=p->next;
p->next=s;
return ok;
}
删除:
Status LinkDelete(LinkList &L,int i,ElemType e){
LNode p=L;
int j=0;
while(p->next&&j<i-1){
p=p->next;
j++;
}
if(!(p->next)||j>i-1)return error;
LNode q=p->next;
p->next=q->next;
e=q->data;
delete q;
return ok;
}
链表的应用:
我们已经知道,在需要进行增删操作时,链表是大大优于顺序表的,所以当经常用到增删操作时就应该采用链表结构。





