c语言 单向链表 自定义基本操作
单向链表和顺序链表比较
在数据的删除和增加方面,单向链表的操作更加方便,只需要找到相应的节点,然后删除该节点或者在这个节点之后增加一个节点,不需要对其他节点进行移动。而顺序表在数据的随机读取方面更加便利,不需要从头结点一个节点一个节点的后移。
单向链表和双向链表相比较
在单向链表上,对于指针的移动,只能从前到后。所以,如果要获的指针前的一个数据,只能让指针从链表的头部开始往后移,如此做会占用大量的时间,扩大运算的时间复杂度。然而双向链表通过多定义一个指针指向前一个节点,使指针可以往前移动,从而减少不必要的操作。
单向链表和单向循环链表相比
两种数据结构类似,只是单向循环链表的最后一个节点的指针域指向的是第一个节点,不是NULL。而且通过定义两个指针,一个指向第一个节点,另一个指向最后一个节点作为标记。防止随后输入的数据把之前输入的数据覆盖。
单向链表的基本操作
我把单向链表的基本操作分为:创建头结点、链表插入节点到正指向指针cur后、链表的指针cur定长n移动、用指针cur搜寻某值为m的节点、删除节点cur、清空链表、清空表头、输出指针cur的值、改变指针变量cur的数据。而其他操作大多可以有这些基本操作相互结合完成。
结构体定义
typedef struct Elem{
int data;//数据
struct Elem * next; //指针
}Elem,*Elemp;
typedef struct {
Elemp head;//头指针
Elemp cur;//正指向的指针
Elemp tail;//尾指针
int elem_length; //链表节点数
int elem_size;//节点大小
}Sqlist,*Sqlistp;
创建头结点函数
status InitList(&L){
Sqlistp L=(Sqlistp)malloc(sizeof(Sqlist));
if(!L) return ERROR;
L->head =(Elemp)malloc(sizeof(Elem));
if(!L->head) return ERROR;
L->cur=L->tail=L->head; L->head->next=NULL;
L->elem_size=sizeof(Elem); L->elem_length=0;
return OK;
}
链表插入节点到正指向指针cur后函数
status addList(&L,m){
if(L==NULL){
printf("表头不存在\n");
return ERROR;
}
Elemp p1=(Elemp)malloc(sizeof(Elem));//申请空间
if(!p1) return ERROR;
p1->next=L->cur->next; L->cur->next=p1; p1->data=m;//节点赋值
L->cur=L->cur->next;//移动指针到添加节点
L->elem_length++;//节点数加一
return OK;
}
链表的指针cur定长n移动函数(起始位置为0)
status moveList(&L,n){
if(L==NULL||L->elem_length==0){
printf("链表不存在\n");
return ERROR;
}
if(n>L->elem_length){
printf("移动失败!\n");
return ERROR;
}
else{
for(i=0;i<n;i++) L->cur=L->cur->next;
return OK;
}
}
用指针cur搜寻某值为m的节点函数
status searchList(&L,m){
if(L==NULL||L->elem_length==0){
printf("链表不存在\n");
return ERROR;
}
L->cur=L->head;
for(;L->cur->next!=NULL&&L->cur->data!=m;) L->cur=L->cur->next;
if(L->cur->data!=m){
printf("没有搜到\n");
return ERROR;
}
else{
printf("找到\n");
return OK;
}
}
删除节点cur函数
stastus delList(&L){
if(L==NULL||L->elem_length==0){
printf("链表不存在\n");
return ERROR;
}
if(L->cur==L->tail){//当删除元素为尾节点
L->tail=L->head;
for(;L->tail->next!=L->cur;) L->tail=L->tail->next;//使尾指针指向前一个节点
}
p2=L->cur;
L->cur=L->cur->next;
free(p2);//释放节点
L->elem_length--;//节点数减一
return OK;
}
清空链表函数
status delallList(&L){
if(L==NULL||L->elem_length==0){
printf("链表不存在\n");
return ERROR;
}
else{
L->cur=L->head->next;//指向第一个节点
for(;L->cur!=NULL;){//节点清空
p2=L->cur;
L->cur=L->cur->next;
free(p2);
}
L->tail=L->head;//表头赋值
L->head->next=NULL;
L->elem_length=0;
return OK;
}
}
清空表头函数
status del(&L){
if(L==NULL){
printf("表头不存在\n");
return ERROR;
}
if(L->head->next!=NULL){
printf("链表非空,请先清空链表\n");
return ERROR;
}
else{
free(L->head);
free(L);
L=NULL;
return OK;
}
}
输出指针cur的值函数
status printfList(&L){
if(L==NULL){
printf("表头不存在\n");
return ERROR;
}
else if(L->elem_length==0){
printf("链表为空\n");
return ERROR;
}
else{
printf(L->cur->data);
return OK;
}
}
改变指针变量cur的数据函数
status printfList(&L,m){
if(L==NULL){
printf("表头不存在\n");
return ERROR;
}
else if(L->elem_length==0){
printf("链表为空\n");
return ERROR;
}
else{
L->cur->data = m;
return OK;
}
}