C语言实现单链表的诸多功能(头插法,尾插法,查找,增添,删除,替换,排序,释放)

实现单链表的诸多功能(头插法,尾插法,查找,增添,删除,替换,排序,释放)

#include<stdio.h>
#include<stdlib.h>
typedef struct node 
{
	int data;
	struct node* next;
} Node;     //创建结构体 struct node 别名Node

/*
头插法:创建指针函数creat1()
*/
Node* creat1(int x)
{
	int e;
	Node* head, * p;  //头指针head,新结点指针p
	head = (Node*)malloc(sizeof(node)); //申请表头存储空间
	head->next = NULL; //表头指针域置为NULL
	printf("请输入%d个任意整数:\n", x);
	/*
	采用for循环给已知结点个数申请空间,并使结点之间相连
	*/
	for (int i = 0; i < x; i++)
	{
		p = (Node*)malloc(sizeof(node));
		scanf_s("%d", &e);
		p->data = e;
		p->next = head->next;
		head->next = p;
}
	return head;// 单链表返回值(表头结点)head
}
/*
尾插法:创建指针函数creat2();
*/
Node* creat2(int x)
{
	int e;
	Node* head, * p, * q;//头指针head,并使p指针也指向表头,q指针是最后遍历单链表输出数据时要用
	head = (Node*)malloc(sizeof(node));
	q = head;
	q->next = NULL; //初始表头结点指针域置为空
	printf("请输入%d个任意整数:\n", x);
	/*
	采用for循环给已知结点个数申请空间,并使结点之间相连
	*/
	for (int i = 0; i < x; i++)
	{
		p = (Node*)malloc(sizeof(node));
		scanf_s("%d", &e);
		p->data = e;
		q->next = p;
		q = p;
	}
	q->next = NULL;
	return head;// 单链表返回值(表头结点)head
}
/*
当在主函数中选用功能1时(头插法),调用此函数
*/

void output1(int n)  
{
	Node* creat1(int x);      //声明单链表头插法函数
	void find(int m, Node * pb);//声明查找函数
	void replace(int m, Node * pb);//声明替换函数
	void insert(int m, Node * pb);//声明插入函数
	void cancle(int m, Node * pb);//声明删除函数
	void sort1(int m, Node * pb);//声明排序函数(从大到小)
	void sort2(int m, Node * pb);//声明排序函数(从小到大)
	void clean(Node*pb);//声明释放内存函数
	Node* pt = creat1(n);//调用单链表头插法函数,并将返回值head赋给pt
	Node* pl = pt;  //这里设置指针pl是方便实行单链表其他的功能(实参)
	/*
	指针pt遍历单链表输出数据
	*/
	pt = pt->next;
	printf("头插法单链表输出数字顺序为:\n");
	for (int i = 0; i < n; i++)
	{
		printf("%d ", pt->data);
		pt = pt->next;
	}
	find(n, pl);//调用查找函数
	replace(n, pl);//调用替换函数
	insert(n, pl);//调用插入函数
	cancle(n,pl);//调用删除函数
	sort1(n,pl);//调用排序函数(从大到小)
	sort2(n, pl);//调用排序函数(从小到大)
	clean(pl);//调用释放内存函数
}
/*
当在主函数中选用功能2时(尾插法),调用此函数
*/

void output2(int n) 
{
	Node* creat2(int x);//声明单链表尾插法函数
	void find(int m, Node * pb);//声明查找函数
	void replace(int m, Node * pb);//声明替换函数
	void insert(int m, Node * pb);//声明插入函数
	void cancle(int m, Node * pb);//声明删除函数
	void sort1(int m, Node * pb);//声明排序函数(从大到小)
	void sort2(int m, Node * pb);//声明排序函数(从小到大)
	void clean(Node*pb);//声明释放内存函数
	Node* pt = creat2(n);//调用尾插法函数,并把函数的返回值head赋给pt
	Node* pl = pt;  //这里设置指针pl是方便实行单链表其他的功能
/*
指针pt遍历链表输出数据
*/
	pt = pt->next;
	printf("头插法单链表输出数字顺序为:\n");
	for (int i = 0; i < n; i++)
	{
		printf("%d ", pt->data);
		pt = pt->next;
	}
	find(n, pl);//调用查找函数
	replace(n, pl);//调用替换函数
	insert(n, pl);//调用插入函数
	cancle(n, pl);//调用删除函数
	sort1(n, pl);//调用排序函数(从大到小)
	sort2(n, pl);//调用排序函数(从小到大)
	clean(pl);//调用释放空间函数
}
/*
查找链表中固定位置数据
*/
void find(int m,Node*pb)
{
	int i;
	int j = 0;
	printf("\n请输入你想查询的的位置(范围:1-%d):\n",m);
	scanf_s("%d", &i);
	if (i > 0 && i <= m)
	{
		while (i!=j)
		{
			pb = pb->next;
			j++;
		}
		printf("查询正确:%d", pb->data);
	}
	else printf("你输入的数字不在范围:(1-%d),查询失败",m);
}
/*
链表中数据的替换
*/
void replace(int m,Node*pb)
{
	int j=0;
	int i,e;
	Node* pc = pb;//创建指针pc也指向表头结点,用指针pb查找指定位置进行替换,用pc指针遍历链表输出替换后数据
	printf("\n请输入你要替换的位置(范围:1-%d):\n", m);
	scanf_s("%d",&i);
	if (i > 0 && i <= m)
	{
		while (i != j)
		{
			pb = pb->next;
            j++;
		}
		printf("请输入你想要替换的数字:\n");
		scanf_s("%d",&e);
		pb->data = e;
		printf("替换数据成功,输出链表结果为:\n");
		pc = pc->next;
		for (int j=0;j<m;j++)
		{
			printf(" %d ", pc->data);
			pc= pc->next;
		}
	}
	else printf("你要替换的位置不在范围:(1-%d)内\n", m);
}
/*
链表中插入数据
*/
void insert(int m,Node*pb)
{
	int i,e;
	int j = 1;
	Node* pc = pb;//创建指针pc指向表头结点,指针pb查找插入位置,并进行插入,指针pc遍历单链表输出插入后的数据
	Node* p;
	printf("\n请输入你要插入的位置(范围:1—%d):\n",m+1);
	scanf_s("%d",&i);
	if (i >= 1 && i <= m + 1)
	{
		while (pb && i != j)
		{
			pb = pb->next;
			j++;
		}
		p = (Node*)malloc(sizeof(node));
		printf("请输入你要插入的数据:\n");
		scanf_s("%d",&e);
		p->data = e;
		p->next = pb->next;
		pb->next = p;
		printf("插入数据成功,输出链表结果:\n");
		pc = pc->next;
		while (pc!=NULL)
		{
			printf("%d ",pc->data);
			pc = pc->next;
		}
	}
	else printf("\n你要插入的位置不在范围(范围:1—%d)",m+1);
}
/*
单链表指定位置删除
*/
void cancle(int m, Node* pb)
{
	int i;
	int j = 0;
	/*
	创建指针pc,p都指向表头结点:
	     指针pc,pb是用来查找删除位置,并进行删除指定位置结点之后对结点进行连接
	     指针p是用来遍历单链表输出删除后数据
	*/
	Node* pc = pb;
	Node* p = pb;
	printf("\n请输入你要删除数据的位置 (范围:1-%d):\n", m + 1);
	scanf_s("%d", &i);
	if (i >= 1 && i <= m + 1)
	{
		while (j != i - 1)
		{
			pc = pb->next;
			pb = pc;
			j++;
		}
		pc = pb->next;
		pb->next = pc->next;
		free(pc);
		printf("数据清除成功,输出链表结果:\n");
		while (p->next)
		{
			p = p->next;
			printf("%d ", p->data);
		}
	}
	else printf("你删除的位置不在范围(范围:1—%d)\n", m + 1);
}
/*
单链表排序(冒泡法:效率高)
*/

void sort1(int m, Node* pb)//从大到小排序
{
	int i, j, n;
	Node* pc=pb;//指针pc指向表头结点
	
	for (i = 0; i < m - 1; i++)
	{
		for (j = 0; j < m-i-1; j++)
		{
			pc=pc->next;
			if (pc->data < pc->next->data)
			{
				n = pc->next->data;
				pc->next->data = pc->data;
				pc->data = n;
			}
		}
		pc = pb;
	}
	pb = pb->next;
	printf("\n单链表从大到小的顺序为:\n");
	for (i=0;i<m;i++)
	{
		printf("%d ",pb->data);
		pb = pb->next;
	}
}

void sort2(int m, Node* pb)//从小到大排序
{
	int i, j, n;
	Node* pc = pb;//指针pc指向表头结点

	for (i = 0; i < m - 1; i++)
	{
		for (j = 0; j < m - i - 1; j++)
		{
			pc = pc->next;
			if (pc->data > pc->next->data)
			{
				n = pc->next->data;
				pc->next->data = pc->data;
				pc->data = n;
			}
		}
		pc = pb;
	}
	pb = pb->next;
	printf("\n单链表从小到大的顺序为:\n");
	for (i = 0; i < m; i++)
	{
		printf("%d ", pb->data);
		pb = pb->next;
	}
}
/*
链表释放(需要两个指针)
*/
void clean(Node*pb)
{
	Node* pc = pb;//指针pc指向表头结点
	while (pb!=NULL)
	{
		pc = pb->next;
		free(pb);
		pb = pc;
    }
	printf("\n单链表存储空间已释放\n");
}
/*
主函数
*/
int main()
{
	int m;
	int n;
	void output1(int n);//声明头插法中诸多功能函数
	void output2(int n);//声明尾插法中诸多功能函数
	printf("\n1.头插法建立链表\n2.尾插法建立链表\n");
	printf("\n请输入选择操作的数字:\n");
	scanf_s("%d", &m);
	printf("请输入你要输入数字的个数:\n");
	scanf_s("%d", &n);
	/*
	功能判断:
	     如果m=1,调用   头插法中诸多功能函数
	     如果m=2,调用   尾插法中诸多功能函数
	*/
	if (m == 1) output1(n);
	if (m == 2) output2(n);
	return 0;
}

运行结果:
在这里插入图片描述
如果有什么地方不合适的话,还请指正哈!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值