前言:
线性表的存储方式除了顺序表外,还有链式存储,通过链式存储的就是链表。
链表分为单链表、双链表、静态链表。
下面先了解一下单链表的结构体以及基本操作方式。
结构体
单链表的结构体主要包含了数据域和指针域两部分,数据域存储了当前节点的数据信息,指针域则代表下一个节点。
typedef struce LNode{
ElemType data;
struct LNode *next;
} LNode,*LinkList;
单链表的初始化
LNode *p;
p = (LNode *) malloc(sizeof(LNode));
p—>data = 20;
p—next = null;
删除节点P的直接后继
q = p—>next;
p->next = q-next;
free(q);
单链表的创建
- 头插法
LinkList creatList(LinkList head){
head = malloc(sizeof(LNode));//初始化头节点
LNode *node = null;//定义工作指针
int count = 0;//记录元素个数
head->next = null;
node = head->next;
scanf("%d",&count);
for(int i=0;i<count;i++){
node = (LNode *)malloc(sizeof(LNode));
node->data=i;
node->=head->next;
head->next=node;
}
return head;
}
2.尾插法
LinkList createListTail(LinkList head){
head = (LinkList) malloc(sizeof(LNode));
LNode node = null;
LNode end = null;
head-next=null;
end = head;
int count=0
scanf("%d",&count);
for(int i=0;i<count;i++){
node = malloc(sizeof(LNode));//为新节点开辟空间
node->data=i;
end-next=node;
end=node;
}
end->next=null;
return head;
}
3.单链表的查找
bool getElem_L(LinkList *L,int i,ElemType &e){
LNode *P;
p = L->next;
int j=1;
while(p && j<i){
p = p->next;
++j;
}
if(!p || j>i){
return false;
}
e = p->data;
return true;
}
大致思路:循环遍历找到下标的指定节点。循环结束的标致为p为空或者j>=i。
4.单链表的按值查找
LNode *LocateNode(LNode *L,int key){
LNode *p = L-next;//定义工作指针
while(p!=null && p->data!=key){
p = p->next;
}
if(p!=null && p->data==key){
return p;
}else{
return false;
}
}
5.单链表的插入操作
在带头节点的单链表L第i个位置插入元素e;
bool ListInsert(LinkList *L,int i,ElemType e){
LNode *p=L;//这里工作指针从头节点开始而不是从第一个数据节点开始,因为有可能插入的位置就是在头节点之后
int j=0;
while(p&& j<i-1){
p = p->next;
j++
}
if(!p || j>i-1){
return false;
}
LNode *s;
s = malloc(sizeof(LNode));
s->data =e;
s->next = p->next;
p->next = s;
return true;
}
6.单链表的删除操作
bool delete(Linklist *L,ElemType e){
LNode *p,LNode *q;
p=L;
int j=0;
while(p && j<i-1){
p=p->next;
j++;
}
if(!p->next || i-1){
q = p->next;
p->next = p->next;
e = q->data;
free(q);
}
}
7. 按值删除
```c
void deleteByValue(){
LNode *p=L,*q = L->next;
while(q !=null && q->next !=key){
//定义两个指针,一个指向删除节点,一个指向被删除节点的前驱
p=q; q = q->next;
}
if(q->data==key){
p->next = q->next;
free(q);
}else{
return false;
}
}
8.将La 和Lb两个有序链表合并成一个有序链表
//合并以La,Lb为头节点两个有序链表
LNode * mergeList(LNode *la,LNode *b){
//合并以La,Lb 为头节点的两个有序链表
LNode *pc,*pa,*pb,*ptr;
Lc = La,pc = pa;pa=La->next;pb=Lb->next;
while(pa!=null && pb!=null){
while( pa->data < pb->data){
pc->next = pa;
pc = pa;
pa = pa->next;
}
if(p->data > p->data){
pc = next=pb;
pc = pb;
pb = pb->next;
}
if(pa->data==pb->data){
pc->next = pa;
pc = pa;
pa = pa->next;
ptr = pb;
pb = pb->next;
free(ptr;);
}
}
if(pa!=null){
pc->next = pa;
}
if(pb!=null){
pc->next = pb;
}
}
9.删除链表中的重复元素
void deleteRepeat(LNode *L){
LNode *p = L->next,*q,*ptr;
while(p!=null){
q = p; ptr=p->next; //p 为工作指针,q则为被删除元素的直接前驱,ptr则为被删除元素的指针
while(ptr!=null){
if(ptr->data == p->data){
q->next = ptr->next;
ptr=q->next;
free(ptr);
}else{
q = ptr;
ptr = ptr->next;
}
}
p = p->next;
}
}
10.将链表实现逆序(采用头插法)
LNode * revertList(LNode *head){
if(null == head->next){
return head;
}
LNode p = head->next;
head->next=null;
while(p){
tmp = p->next;
p->next = head->next;
head->next = p;
p=tmp;
}
retrun head;
}