单链表的创建以及增、删、改、查。

本文介绍如何使用C语言实现链表的创建,包括无序链表`create_linklist`和有序链表`create_linklist2`,以及如何在有序链表中插入数据`insert_data`。讲解了插入节点的方法,如头插法、尾插法和保持链表有序的逻辑。
摘要由CSDN通过智能技术生成
#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);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值