#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
//链表中保存的是“结点(用户数据/关系)”
typedef struct node
{
ElemType data; //数据域
struct node *next; //结点的下一个元素的地址
}Node;
/*
create_linklist:根据用户的输入创建一个链表
返回值:
返回创建好的链表的第一个结点的地址
*/
Node* create_linklist()
{
Node *first=NULL; //保存新创建的链表的第一个结点的地址
Node *last=NULL; //保存新创建的链表的最后一个结点的地址
while(1)
{
//获取用户的输入,当用户输入0的时候输入结束。
ElemType d;
scanf("%d",&d);
if(d == 0)
{
break;
}
//创建一个结点并且初始化
//动态分配一个结点空间,存储当前用户输入的数据
Node *p = (Node *)malloc(sizeof(Node));
p->data = d; //保存数据
p->next = NULL;
//把结点加入到first表示的链表中
if(first == NULL) //链表中暂时还没有结点,链表为空
{
first = p;
last = p;
}else
{
//头插法:新元素放到已有链表的前面,按照用户的输入序列的反序建立链表
//p->next = first;
//first = p;
//尾插法:新元素放到已有链表的后面,按照用户的输入序列建立链表
last->next = p;
last = p;
}
}
return first;
}
/*
create_linklist2:根据用户的输入创建一个有序链表
返回值:
返回创建好的链表的第一个结点的地址
*/
Node* create_linklist2()
{
Node *first=NULL; //保存新创建的链表的第一个结点的地址
Node *last=NULL; //保存新创建的链表的最后一个结点的地址
while(1)
{
//获取用户的输入
ElemType d;
scanf("%d",&d);
if(d == 0)
{
break;
}
//创建一个结点并且初始化
//动态分配一个结点空间,存储当前用户输入的数据
Node *p = (Node *)malloc(sizeof(Node));
p->data = d; //保存数据
p->next = NULL;
//把结点加入到first表示的链表中
if(first == NULL) //链表中暂时还没有结点,链表为空
{
first = p;
last = p;
}else
{
//根据当前情况,把新结点p加入到不同的位置
if(p->data <= first->data) //第一个结点就比p大-->头插法
{
p->next = first;
first = p;
}else if(p->data >= last->data) //比最后一个结点大 --->尾插法
{
last->next = p;
last = p;
}else
{
Node *pk = NULL; //保存第一个比新结点值大的那一个结点
Node *pr = NULL; //pk前面的结点
pk = first; //从第一个开始遍历
while(pk) //pk!=NULL
{
if(pk->data > p->data) //当前的值就比新结点的值大
{
break;
}
pr = pk; //记录pk的前一个数据
pk = pk->next;
}
//找到一个合适的位置
p->next = pk;
pr->next = p;
}
}
}
return first;
}
/*
insert_data:把一个指定数据data插入到一个有序的链表,使链表任然有序
@list:你要插入的链表
@data:你要插入的数据
返回值:
返回插入后的链表的第一个结点的地址
*/
Node *insert_data(Node *list,ElemType data)
{
Node *first=list;
Node *last=NULL;
//根据first找到last
last = first;
if(last != NULL)
{
while(last->next != NULL)
{
last = last->next;
}
}
//动态分配一个结点空间,存储当前用户输入的数据
Node *p = (Node *)malloc(sizeof(Node));
p->data = data; //保存数据
p->next = NULL;
//把结点加入到first表示的链表中
if(first == NULL) //链表中暂时还没有结点,链表为空
{
first = p;
last = p;
}else
{
//根据当前情况,把新结点p加入到不同的位置
if(p->data <= first->data) //第一个结点就比p大-->头插法
{
p->next = first;
first = p;
}else if(p->data >= last->data) //比最后一个结点大 --->尾插法
{
last->next = p;
last = p;
}else
{
Node *pk = NULL; //保存第一个比新结点值大的那一个结点
Node *pr = NULL; //pk前面的结点
pk = first; //从第一个开始遍历
while(pk) //pk!=NULL
{
if(pk->data > p->data) //当前的值就比新结点的值大
{
break;
}
pr = pk; //记录pk的前一个数据
pk = pk->next;
}
//找到一个合适的位置
p->next = pk;
pr->next = p;
}
}
return first;
}
/*
print_list:打印指定的链表中的所有的数据
@list:指向你要打印的链表的第一个结点
返回值:无
*/
void print_list(Node *list)
{
if(list == NULL)
{
printf("链表为空!!\n");
return;
}
//遍历list表示的链表的每一个结点,打印数据域
printf("list data:");
Node *p = list;
while(p) //p!=NULL
{
printf("%d ",p->data);
p = p->next;//指向下一个结点
}
printf("\n");
}
/*
delete_list:删除链表,释放所有结点空间
*/
void delete_list2(Node **list)
{
Node *p = *list;
while(p)
{
*list = (*list)->next;
free(p);
p = *list;
}
return;
}
/*
delete_min:删除指定的链表中的值最小的结点
@list:指向你要操作的链表的第一个结点
返回值:
返回删除最小值后的链表的第一个结点的地址
*/
Node *delete_min(Node *list)
{
if(list == NULL) //传入的是一个空链表
{
return NULL;
}
//(1)找到那个要删除的结点px
//遍历链表,找到要删除的结点px,以及px前面的那一个结点pr
Node *px = list; //指向要删除的
Node *pr = list; //指向要删除的前面的那一个结点
Node *p = list;
Node *r = list;
while(p) //p!=NULL
{
if(p->data < px->data) //更新最小值
{
pr = r;
px = p;
}
r = p;//r永远指向p前面的那一个结点
p = p->next;
}
//循环结束,px肯定就指向最小值
/*
while(pr && pr->next != px)
{
pr = pr->next;
}
*/
//(2)分情况删除
//a.删除第一个结点(px == first)
if(px == list)
{
list = list->next;
px->next = NULL;
free(px);//释放px指向的结点
}else if(px->next == NULL)
{
//b.删除最后一个结点(px->next = NULL)
pr->next = NULL;
free(px);//释放px指向的结点
}else
{
//c.删除的结点是中间的结点
pr->next = px->next;
px->next = NULL;
free(px);
}
return list;
}
/*
delete_x:删除指定的链表中的值为x的结点
@list:指向你要操作的链表的第一个结点
@x:你要删除的值
返回值:
返回删除x后的链表的第一个结点的地址
*/
Node *delete_x(Node *list,ElemType x)
{
if(list == NULL) //传入的是一个空链表
{
return NULL;
}
Node *p = list;
Node *pr = p;
while(1)
{
//(1)找到那个要删除的结点px以及px前面的那一个结点pr
Node *px = p;
while(px)
{
if(px->data == x) //px中保存的数据就是x
{
p = px->next;//记录当前的x的下一个结点,作为下一次查找的起点
break;
}
pr = px;
px = px->next;
}
//上面的循环有两个出口(px == NULL 或者是px指向了要删除的结点)
if(px == NULL) //当前链表中没有x
{
return list;
}
//(2)分情况删除
if(px == list) //要删除的结点是第一个结点
{
list = list->next;
px->next = NULL;
free(px);
}else
{
pr->next = px->next;
px->next = NULL;
free(px);
}
}
}
单链表的创建以及增、删、改、查。
于 2022-03-02 22:13:41 首次发布
本文介绍如何使用C语言实现链表的创建,包括无序链表`create_linklist`和有序链表`create_linklist2`,以及如何在有序链表中插入数据`insert_data`。讲解了插入节点的方法,如头插法、尾插法和保持链表有序的逻辑。
摘要由CSDN通过智能技术生成