目录
一.单链表的建立
1.尾插法
第一种方法:
尾插法建立单链表:
初始化单链表
设置变量length记录链表长度
While循环{
每次取一个数据元素e;
ListInsert (L, length+1, e)插到尾部;
length++;
}
但是每次都要从头开始遍历,时间复杂度为O(n2).
第二种方法:
LinkList List_Taillnsert(LinkList &L){ // 正向建立单链表
int x;//设ElemType为整型
L=(LinkList)malloc(sizeof(LNode)); //建立头结点
LNode *s,*r=L;//r为表尾指针
scanf("%d" ,&x);//输入结点的值
while(x!=9999){//输入9999表示结束
s=(LNode * )malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;//r指向新的表尾结点
scanf("%d",&x);
}
r->next=NULL;//尾结点指针置空
return L;
}
后插法,更较简单,不用一次次遍历。
2.头插法
头插法建立单链表:
初始化单链表
While 循环 {
每次取一个数据元素e;
InsertNextNode (L, е);
}
//后插操作:在p結点之后插入元素e
bool InsertNextNode (LNode *p, ElemType e){
if (p==NULL)
return false;
LNode *S = (LNode * )malloc(sizeof (LNode));
if (s==NULL)//内存分配失败
return false;
s->data = e;//用结点s保存数据元素e
s->next=p->next;
p->next=s;//將结点s连到p之后
return true;
}
要养成好习惯,只要是初始化单链表,都先把头指针指向NULL(L->next=NULL;),初始为空链表
头插法就相当于链表的逆置
头插法和尾插法:核心就是初始化操作,指定结点的后插操作。
二.双链表
1.双链表的初始化
头结点的prior、next都指向NULL
typedef struct DNode{
ElemType data;
struct DNode *prior ,*next;
}DNode, *DLinklist;
//初始化双鏈表
bool InitDLinkList(DLinklist &L){
L = (DNode *) malloc(sizeof(DNode)); //分配一个头结点
if (L==NULL)//内存不足,分配失敗
return false;
L->prior = NULL;//头结点的prior永远指向NULL
L->next = NULL;、/头结点之后暂吋还没有结点
return true;
}
void testDLinkList() {//初始化双链表
DLinklist L;
InitDLinkList(L);//后续代码
}
2.双链表的插入
注意新插入结点、前驱结点、后继结点的指针修改
边界情况:新插入结点在最后一个位置,需特殊处理
修改指针时要注意顺序
//在p结点之后插入s结点
bool Inser tNextDNode(DNode *p, DNode *s){
if (p==NULL || S==NULL)//非法参数
return false;
s->next=p->next;
if (p->next != NULL)//如果p结点有后继结点
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
3.双链表的删除
注意删除结点的前驱结点、后继结点的指针修改
边界情况:如果被删除结点是最后-个数据结点,需特殊处理
//删除p结点的后继结点
bool DeleteNextDNode(DNode *p){
if (p==NULL)
return false;
DNode *q = p->next;//找到p的后继结点q
if (q==NULL)
return false;//p没有后继
p->next=q->next;
if (q->next !=NULL)//q结点不是最后一个结点
q->next->prior=p;
free(q);//释放结点空间
return true;
}
如果要将双链表删除,则要加上这个函数
void DestoryList(DLinklist &L){//循环释放各个数据结点
while (L->next != NULL)
DeleteNextDNode(L);
free(L); //释放头结点
L=NULL;//头指针指向NULL
}
4.双链表的遍历
从一个给定结点开始,后向遍历、前向遍历的实现(循环的终止条件)
链表不具备随机存取特性,查找操作只能通过顺序遍历实现
后向遍历
while (p!=NULL){
//对结点p做相应处理,如打印
p= p->next;
}
前向遍历
while (p!=NULL){
//对结点p做相应处理
p= p->prior;
}
前向遍历(跳过头结点)
while (p-> prior != NULL){
//对结点p做相应处理
p= p->prior;
}
双链表不可随机存取,按位查找、按值查找操作都只能用遍历的方式实现。时间复杂度O(n)