学习严蔚敏老师《数据结构(C语言版)》,关于单链表的基本操作:
1.单链表的存储结构
2.初始化 InitList_L
3.在带头结点的单链表中第i个位置之前插入元素e ListInsert_L【2.9】
4.头插法建立单链表L(逆序输入)CreateList_HL【2.11】
5.尾插法建立单链表L(顺序输入)CreateList_TL
6.在带头结点的单链表中删除第i个元素,并用e返回其值 ListDelete_L【2.10】
7.遍历单链表 ListTraverse_L
8.置空单链表 ClearList_L
9.销毁单链表 DestroyList_L
10.判断是否为空表 ListEmpty_L
11.L中的数据元素个数 ListLength_L
12.返回L中第i个元素的值 GetElem_L【2.8】
13.返回L中第一个与e满足关系compare()的数据元素的位序 LocateElem_L
14.找前驱 PriorElem_L
15.找后继 NextElem_L
#include<stdio.h>
#include<stdlib.h>
typedef int Status; //状态码识别类型
typedef int ElemType;
#define OVERFLOW -2 //堆栈上溢
#define UNDERFLOW -3 //堆栈下溢
//▲01单链表的存储结构
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
//▲02初始化
Status InitList_L(LinkList &L){
L=(LinkList)malloc(sizeof(LNode));
if(!L){
exit(OVERFLOW);
}
L->next=NULL;
return 1;
}
//▲03在带头结点的单链表中第i个位置之前插入元素e
Status ListInsert_L(LinkList L,int i,ElemType e){
LinkList p,s;
int j=0;
p=L;
while(p&&j<i-1){//寻找第i-1个节点
p=p->next;
j++;
}
if(!p||j>i-1){
return 0;
}
s=(LinkList)malloc(sizeof(LNode)); //生成新结点
s->data=e;
s->next=p->next;
p->next=s;
return 1;
}
//▲04头插法 逆位序输入n个元素的值,建立带表头结点的单链线性表L
void CreateList_HL(LinkList &L,int n){
LinkList p;
L=(LinkList)malloc(sizeof(LNode));//创建头结点
L->next=NULL;//初始化为空的单链表
for(int i=n;i>0;i--){
p=(LinkList)malloc(sizeof(LNode));
scanf("%d",&p->data);
p->next=L->next;
L->next=p;
}
}
//▲05尾插法
void CreateList_TL(LinkList &L,int n){
LinkList p,q;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
q=L;//q始终指向尾结点,开始时头结点和尾结点是同一个
for(int i=1;i<=n;i++){
p=(LinkList)malloc(sizeof(LNode));
scanf("%d",&p->data);
q->next=p;
q=p;//q指向新的表尾结点
}
q->next=NULL;
}
//▲06在带头结点的单链表中删除第i个元素,并用e返回其值
Status ListDelete_L(LinkList &L,int i,ElemType &e){
LinkList p,q;
int j=0;
p=L;
while(p->next&&j<i-1){ //寻找第i个节点,并令p指向其前驱
p=p->next;
j++;
}
if(!(p->next)||j>i-1){
return 0;
}
//p->next=p->next->next;
q=p->next;
p->next=q->next;
e=q->data;
free(q);
return 1;
}
void PrintElem(ElemType e){
printf("%d ", e);
}
//▲07遍历单链表
Status ListTraverse_L(LinkList L,void (visit)(ElemType)){
LinkList p;
if(!L){
return 0;
}else{
p=L->next;
}
while(p){
visit(p->data);
p=p->next;
}
printf("\n");
return 1;
}
//▲08置为空链表,保留头结点
Status ClearList_L(LinkList L){
LinkList pre,p;
if(!L){
return 0;
}
pre=L->next;
while(pre){
p=pre->next;
free(pre);
pre=p;
}
L->next=NULL;
return 1;
}
//▲09销毁单链表
void DestroyList_L(LinkList &L){
LinkList p=L;
while(p){
p=L->next;
free(L);
L=p;
}
}
//▲10判断是否为空表
Status ListEmpty_L(LinkList L){
if(L!=NULL&&L->next==NULL){//链表存在并且只有头结点
return 1;
} else{
return 0;
}
}
//▲11单链表L中的元素个数
int ListLength_L(LinkList L){
LinkList p;
int i;
if(L){
i=0;
p=L->next;
while(p){
i++;
p=p->next;
}
}
return i;
}
//▲12返回第i个元素的值
Status GetElem_L(LinkList L,int i,ElemType *e){
LinkList p;
int j=1;
p=L->next; //p指向第一个结点
while(p&&j<i){
p=p->next;
j++;
}
if(!p||j>i){ //第i个元素不存在
return 0;
}
*e=p->data;
return 1;
}
Status CmpGreater(ElemType e, ElemType data){
return data>e?true:false;
}
//▲13 返回L中第一个与e满足关系compare()的数据元素的位序
int LocateElem_L(LinkList L, ElemType e, Status (Compare)(ElemType,ElemType)){
LinkList p;
int i=0;
if(!L){ //L不存在时返回-1
return -1;
}
p=L->next;
while(p){
i++;
if(!Compare(e,p->data)){
p=p->next;
if(p==NULL){
i++;
}
}else{
break;
}
}
return i;
}
//▲14 找前驱
Status PriorElem_L(LinkList L, ElemType cur_e, ElemType &pre_e){
LinkList p,q;
if(L){
p=L->next;
if(p->data!=cur_e){ //第一个结点无前驱
while(p->next){
q=p->next; //q指向p的后继
if(q->data==cur_e){
pre_e=p->data;
return 1;
}
p=q;
}
}
}
return 0;
}
//▲15 找后继
Status NextElem_L(LinkList L, ElemType cur_e, ElemType &next_e){
LinkList p,q;
if(L){
p=L->next;
while(p&&p->next){
q=p->next; //q指向p的后继
if(q && p->data==cur_e){ //最后一个结点无后继
next_e=q->data;
return 1;
}
if(q){
p=q;
}else{
break;
}
}
}
return 0;
}
//▲16 删除值为e的第一个结点
Status ListDelete2_L(LinkList L,ElemType e){
LinkList p,q;
p=L;
q=L->next;
while(q!=NULL&&q->data!=e){
p=q;
q=q->next;
}
if(q->data==e){
p->next=q->next;
free(q);
return 1;
}else{
return 0;
}
}
int main(){
LinkList L;
ElemType e;
int i;
printf("———————————————————————▲02初始化为空表\n");
InitList_L(L);//初始化
printf("———————————————————————▲10判空\n");
if(ListEmpty_L(L)){//判空
printf("L为空表\n");
} else{
printf("L为非空表\n");
}
printf("———————————————————————▲03插入\n");
for(int i=1;i<=6;i++){
ListInsert_L(L,i,i-1);//在第i个位置前插入值为i-1的数据元素
}
ListTraverse_L(L,PrintElem);//遍历
printf("———————————————————————▲06删除 & ▲11元素个数\n");
printf("当前L中的元素个数为:%d\n",ListLength_L(L));
ListDelete_L(L,2,e);//删除第2个元素
ListTraverse_L(L,PrintElem);
printf("此时L中的元素个数为:%d\n",ListLength_L(L));
printf("———————————————————————▲12位序上的元素值\n");
GetElem_L(L,2,&e);
printf("此时L中第2个数据元素为:%d\n",e);
printf("———————————————————————▲13满足关系的位序\n");
printf("L中第一个元素值大于2的元素所在的位置是%d\n",LocateElem_L(L,2,CmpGreater));
printf("———————————————————————▲14前驱 & ▲15后继\n");
PriorElem_L(L,2,e);
printf("元素2的前驱为:%d\n",e);
NextElem_L(L,2,e);
printf("元素2的后继为:%d\n",e);
printf("———————————————————————▲06置空\n");
printf("清空操作前:");
ListEmpty_L(L) ? printf(" L为空表!\n") : printf(" L不为空表!\n");
ClearList_L(L);//置为空表
printf("清空操作后:");
ListEmpty_L(L) ? printf(" L为空表!\n") : printf(" L不为空表!\n");
printf("———————————————————————▲09销毁\n");
printf("销毁L前:");
L ? printf("L存在!\n") : printf("L不存在!\n");
DestroyList_L(L);//销毁线性表
printf("销毁L后:");
L ? printf("L存在!\n") : printf("L不存在!\n");
printf("———————————————————————▲04头插 & ▲05尾插\n");
printf("头插法建立单链表:");
CreateList_HL(L,5);
ListTraverse_L(L,PrintElem);//遍历
printf("尾插法建立单链表:");
CreateList_TL(L,5);
ListTraverse_L(L,PrintElem);//遍历
printf("———————————————————▲16 删除值为3的第一个结点\n");
ListDelete2_L(L,3);
ListTraverse_L(L,PrintElem);
return 0;
}