单链表的创建、插入、删除、查找、取值、输出、退出功能实现

目录

结构体和头文件

全局声明

建表函数

插入函数

删除函数

查找函数

取值函数

输出函数

退出函数

菜单函数 

主函数

完整代码


完整代码在最下面

结构体和头文件

#include<stdio.h>
#include<stdlib.h>
typedef struct linklist
{
	int data;//数据域
	struct linklist* next;指针域
}linklist;

全局声明

linklist* head;

建表函数

      尾插法演示:

linklist* createlist(int i)//传递参数i,i是链表长度
{
	linklist* p;
	linklist* r;
	linklist* head;
	head = (linklist*)malloc(sizeof(linklist));//开辟头节点
	head->next = NULL;//将头节点的next指向null
	r = (linklist*)malloc(sizeof(linklist));//开辟r结点
	head = r;//把r结点等于头节点
	int n;
	printf("请输入数字:");
	for (n = 0; n < i; n++)
	{
		p = (linklist*)malloc(sizeof(linklist));//注意循环开辟p结点
		scanf("%d", &p->data);//给p结点的data赋值
		r->next = p;//将r的next指向p
		r = p;//r结点等于p结点
	}
	r->next = NULL;//r的next指向null
	printf("创建链表成功\n");
	return head;返回头节点
}

      linklist* createlist(int i),int(i)最后解释。

      尾插法的要点在于在头节点后面开辟结点,然后连接上一个结点,字面上理解很抽象,我画了一幅图,简化为以下五步。有点丑,不要介意。

第一步:开辟了头节点。

第二步:r结点等于头节点,也就是让r指向head的数据域和指针域。

第三步:第三步开辟了p结点,并把3赋值给p的数据域。

第四步:把新开辟的p结点连上头节点,也就是r->next = p;(注意此时r=head)。

第五步:把r结点等于p结点。

      ④⑤是尾插法的精髓,创建很多结点再把他们头尾相连形成链表,就在于不断开辟新的p结点,给他们的数据域赋值,然后与上一个r结点相连接,最后把r结点等于新开辟的p结点。这也就是为什么要把以下四步放入循环中。

      p = (linklist*)malloc(sizeof(linklist));
      scanf("%d", &p->data);
      r->next = p;
      r = p;

如果再开辟一个新的p结点,操作如下:

最后不要忘记把head的null赋给移动到最后的r结点。 

int i;是主函数传递的实际参数给建表函数,以下是主函数里的建表函数。

主函数里给i赋值,然后把i传递给建表函数,当然也可以把printf和scanf两句放到建表函数里。

插入函数

linklist* insertlist(linklist* head, int a, int e, int i)//传递参数,a是插入位置,e是需要插入的数值,i是链表长度
{
	linklist* s = (linklist*)malloc(sizeof(linklist));//开辟s结点
	linklist* p = head;//p结点等于头节点
	s->next = NULL;//s的next指向null
	s->data = e;//将s的data赋值给e
	int j = 0;
	if (a >= i || a < 0)//如果插入的位置小于0或大于链表长度,则输入位置有误
	{
		printf("插入位置输入错误!\n");
		exit(1);
	}
	while (p != NULL)//见详解
	{
		if (j == a)
		{
			s->next = p->next;
			p->next = s;
		}
		p = p->next;
		j++;
	}
    i++;
	printf("%d在第%d号位插入成功!\n", e, a);
	return head;
}

       插入的要点在于将新开辟的s结点的data赋值,然后先与后一个结点相连,再与上一个结点相连,如图:

      如果①②对换顺序,先p->next = s;再s->next = p->next;此时p的next已经等于了s,再到s->next = p->next;时,就变成了s->next = s;,所以①②的顺序不能对换。

主函数里的插入函数: 

      linklist* p = head;

因为while循环里p = p->next;遍历结点,所以要把p赋给头结点。

      int j=0;

什么时候插入s结点,需要一个计数器,j就充当了这个位置,当输入的位置a与j相等时,说明就在此时进入if语句并插入s结点。

删除函数

linklist* detellist(linklist* head, int a, int i)//a是删除的位置,i是链表长度
{
	linklist* p = head;
	linklist* q = (linklist*)malloc(sizeof(linklist));//开辟q结点
	int j = 0;
	if (a > i || a < 0)
	{
		printf("删除位置输入错误!\n");//如果插入的位置小于0或大于链表长度,则输入位置有误
		exit(1);
	}
	while (p != NULL)
	{
		if (j == a)
		{
			q = p->next;
			p->next = q->next;
		}
		p = p->next;
		j++;
	}
	printf("%d删除成功\n", q->data);
	free(q);//释放q结点
	return head;
}

      当j==a,也就是输入的位置与需要删除的位置相等时,进入if语句,q等于p的下一个结点,也就是需要删除的结点,先把p与q的下一个结点相连,再释放q结点,如果先释放q结点,会导致断链。

举个例子更好理解:

      比如我需要删除2(2的位置为1),输入a=1,第一次循环p=head,j=0,a=1,不进入if语句;程序走过p=p->next,j++后,此时进入第二次循环,j==a==1,进入if语句q = p->next,q就指向了2所在结点,p再绕过q连接下一个结点,随后释放p结点。代码里之所以没有写为

while (p != NULL)
{
	if (j == a)
	{
		q = p->next;
		p->next = q->next;
		free(q);
	}
	p = p->next;
	j++;
}

是因为printf("%d删除成功\n", q->data);中用到了q。

操作如图:

查找函数

linklist* searchlist(linklist* head,int e)
{
	linklist* p;
	p = head->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	if (p->data == e)
		printf("%d的地址为:%p", e, p);
	else
	{
		printf("查找数值输入错误!");
		exit(1);
	}
	return head;
}

      查找比较简单,让p遍历链表,输出与e相等的p->data的p的地址。注意p=head->next,因为head始终是空的,还有while里的循环条件。

取值函数

linklist* getlist(int i, int a)//i是链表长度,a是需要取值的位置
{
	linklist* p;
	int e;
	p = head->next;
	int j = 0;
	if (a >= i || a < 0)//如果插入的位置小于0或大于链表长度,则输入位置有误
	{
		printf("取值位置输入错误!\n");
		exit(1);
	}
	while (p != NULL && a != j ) 
	{
		p = p->next;
		j++;
	}
	if (a == j)
		printf("%d号位是%d", a, p->data);
	return head;
}

      要输出序号,就需要一个计数器,这里j充当计数器,当j与需要取值的位置a相等时,输出此时p的data即可。注意如果输入的是1 2 3,实际上的位置是0 1 2。 同样需要注意while里的条件。

输出函数

linklist* inputlist(linklist* head)
{
	linklist* p = head;
	p = head->next;
	printf("顺序表里的元素有:\n");
	while (p != NULL)
	{
		printf("%d   ", p->data);
		p = p->next;
	}
	return head;
}

      p遍历链表并输出p的data,注意p = head->next。

退出函数

linklist* outlist(linklist* head)
{
	linklist* p = head;
	linklist* d;
	p = head->next;
	while (p != NULL)
	{
		linklist* d = (linklist*)malloc(sizeof(linklist));
		d = p;
		p = p->next;
		free(d);
	}
	printf("退出成功!");
	return head;
}

操作如图:

      因为d最后要被释放,所以开辟d放入循环里,每次重新开辟。

菜单函数 

void menu()
{
	printf("\n****************************************************************\n");
	printf("\n***********            请输入你的选择                ***********\n");
	printf("\n***********          1 ---- 建表                     ***********\n");
	printf("\n***********          2 ---- 插入                     ***********\n");
	printf("\n***********          3 ---- 删除                     ***********\n");
	printf("\n***********          4 ---- 查找                     ***********\n");
	printf("\n***********          5 ---- 取值                     ***********\n");
	printf("\n***********          6 ---- 输出链表                 ***********\n");
	printf("\n***********          0 ---- 退出                     ***********\n");
	printf("\n****************************************************************\n");
}

主函数

int main()
{
	int i, a, e;
	while (1)
	{
		menu();
		int choice;
		printf("请选择功能:");
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
			printf("请输入创建的链表的长度:");
			scanf("%d", &i);
			head = createlist(i);
			break;
		case 2:
			printf("请输入需要插入的位置:");
			scanf("%d", &a);
			printf("请输入需要插入的数字:");
			scanf("%d", &e);
			insertlist(head, a, e, i);
			break;
		case 3:
			printf("请输入需要删除的位置:");
			scanf("%d", &a);
			detellist(head, a, i);
			break;
		case 4:
			printf("请输入需要查找地址的数:");
			scanf("%d", &e);
			searchlist(head, e);
			break;
		case 5:
			printf("请输入需要取值的位置:");
			scanf("%d", &a);
			getlist(i, a);
			break;
		case 6:
			inputlist(head);
			break;
		case 0: 
			outlist(head);
			break;
		}
	}
	return 0;
}

完整代码

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef struct linklist
{
	int data;
	struct linklist* next;
}linklist;

linklist* head;

void menu()
{
	printf("\n****************************************************************\n");
	printf("\n***********            请输入你的选择                ***********\n");
	printf("\n***********          1 ---- 建表                     ***********\n");
	printf("\n***********          2 ---- 插入                     ***********\n");
	printf("\n***********          3 ---- 删除                     ***********\n");
	printf("\n***********          4 ---- 查找                     ***********\n");
	printf("\n***********          5 ---- 取值                     ***********\n");
	printf("\n***********          6 ---- 输出链表                 ***********\n");
	printf("\n***********          0 ---- 退出                     ***********\n");
	printf("\n****************************************************************\n");
}

linklist* createlist(int i)
{
	linklist* p;
	linklist* r;
	linklist* head;
	head = (linklist*)malloc(sizeof(linklist));
	head->next = NULL;
	r = (linklist*)malloc(sizeof(linklist));
	r = head;
	int n;
	printf("请输入数字:");
	for (n = 0; n < i; n++)
	{
		p = (linklist*)malloc(sizeof(linklist));
		scanf("%d", &p->data);
		r->next = p;
		r = p;
	}
	r->next = NULL;
	printf("创建链表成功\n");
	return head;
}

linklist* insertlist(linklist* head, int a, int e, int i)
{
	linklist* s = (linklist*)malloc(sizeof(linklist));
	linklist* p = head;
	s->next = NULL;
	s->data = e;
	int j = 0;
	if (a >= i || a < 0)
	{
		printf("插入位置输入错误!\n");
		exit(1);
	}
	while (p != NULL)
	{
		if (j == a)
		{
			s->next = p->next;
			p->next = s;
		}
		p = p->next;
		j++;
	}
	printf("%d在第%d号位插入成功!\n", e, a);
	return head;
}

linklist* detellist(linklist* head, int a, int i)
{
	linklist* p = head;
	linklist* q = (linklist*)malloc(sizeof(linklist));
	int j = 0;
	if (a >= i || a < 0)
	{
		printf("删除位置输入错误!\n");
		exit(1);
	}
	while (p != NULL)
	{
		if (j == a)
		{
			q = p->next;
			p->next = q->next;
		}
		p = p->next;
		j++;
	}
	printf("%d删除成功\n", q->data);
	free(q);
	return head;
}

linklist* searchlist(linklist* head,int e)
{
	linklist* p;
	p = head->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	if (p->data == e)
		printf("%d的地址为:%p", e, p);
	else
	{
		printf("查找数值输入错误!");
		exit(1);
	}
	return head;
}

linklist* getlist(int i, int a)
{
	linklist* p;
	p = head->next;
	int j = 0;
	if (a >= i || a < 0)
	{
		printf("取值位置输入错误!\n");
		exit(1);
	}
	while (p != NULL && a != j ) 
	{
		p = p->next;
		j++;
	}
	if (a == j)
		printf("%d号位是%d", a, p->data);
	return head;
}

linklist* inputlist(linklist* head)
{
	linklist* p = head;
	p = head->next;
	printf("顺序表里的元素有:\n");
	while (p != NULL)
	{
		printf("%d   ", p->data);
		p = p->next;
	}
	return head;
}

linklist* outlist(linklist* head)
{
	linklist* p = head;
	linklist* d;
	p = head->next;
	while (p != NULL)
	{
		linklist* d = (linklist*)malloc(sizeof(linklist));
		d = p;
		p = p->next;
		free(d);
	}
	printf("退出成功!");
	return head;
}

int main()
{
	int i, a, e;
	while (1)
	{
		menu();
		int choice;
		printf("请选择功能:");
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
			printf("请输入创建的链表的长度:");
			scanf("%d", &i);
			head = createlist(i);
			break;
		case 2:
			printf("请输入需要插入的位置:");
			scanf("%d", &a);
			printf("请输入需要插入的数字:");
			scanf("%d", &e);
			insertlist(head, a, e, i);
			break;
		case 3:
			printf("请输入需要删除的位置:");
			scanf("%d", &a);
			detellist(head, a, i);
			break;
		case 4:
			printf("请输入需要查找地址的数:");
			scanf("%d", &e);
			searchlist(head, e);
			break;
		case 5:
			printf("请输入需要取值的位置:");
			scanf("%d", &a);
			getlist(i, a);
			break;
		case 6:
			inputlist(head);
			break;
		case 0: 
			outlist(head);
			break;
		}
	}
	return 0;
}

  • 10
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脑子不好真君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值