C语言单链表入门讲解(附例题)

“ Ctrl AC!一起 AC!”

目录

前言:

单链表的定义及结点:

单链表的定义:

单链表结点的结构体:

单链表的建立:

在单链表中插入一个数据为x的新结点:

尾插法建立链表:

单链表的遍历:

遍历释放内存:

遍历输出数据:

单链表查找并删除结点:

查找结点核心代码:

删除结点核心代码:

查找并删除结点函数:

例题:


前言:

讲单链表前,先说一下数组:

数组是一种线性数据结构,它可以实现对数据元素的随机访问,但当在有序数组中插入或删除数据且保持有序性时需移动大量元素;同时数组在内存中占用连续的储存空间,在定义时大小固定,当数据量超过数组容量时,不能动态扩展新的存储空间。

而同为线性数据结构的链表可以很好解决上述问题。链表是线性结构的另一种有效存储结构,它为线性结构中的各元素独立地申请存储空间,并且在每个元素内增设指针来记录其前驱或后继元素的位置。因此能提高内存空间的利用率和动态扩展。

单链表的定义及结点:

单链表的定义:

单链表是由一连串的结构(称为结点)组成的,其中每个结点除了包含所存储对象外的全部属性外,还包含指向链表中下一个结点的指针。

链表中的最后一个结点包含空指针,并通过一个额外的指针记住第一个结点的位置。

单链表结点的结构体:

//第一种(推荐)
struct node
{
	int data;
	struct node* next;
};
typedef struct node linknode;
typedef linknode* linklist;
linklist p;//定义链表结点指针
//第二种
struct node
{
	int data;
	stuct node* next;
}linknode;
linknode* p;//定义链表结点指针

这样就能通过指针找到下一结点。

单链表的建立:

在单链表中插入一个数据为x的新结点

先准备一个指针:

linklist q;
q=(linklist)malloc(sizeof(linknode)) //申请内存
q->data = x //存入数据

插入第一种情况(插入到链表最前面或插入到一个空链表)

q->next = head;
head = q;

插入第二种情况(插入到p指向的结点的后面(p!=尾指针))

q->next = p->next;
p->next = q;

插入第三种情况(插入到最末尾,tail为尾指针)

tail->next = q;
tail = q;
tail = NULL

尾插法建立链表:

linklist creatLink()
{
	linklist head = NULL, tail == NULL, q; //初始空链表,q为临时结点
	int x;
	printf("请输入整数序列,以-1结束\n");
	scanf("%d", &x);
	while (x != -1)
	{
		q = (linklist)malloc(sizeof(linknode));
		q->data = x;
		if (head == NULL)//链表为空
			head = tail = q;
		else//链表不为空
		{
			tail->next = q;
			tail = q;
		}
        scanf("%d", &x);
    }
	if (tail != NULL) tail->next = NULL;//链表置尾结束
	return head;
}

单链表的遍历:

遍历释放内存:

链表建立过程中申请来的空间用完后需要释放掉,可通过遍历释放。

如码:

void freeLinklist(linklist head) {//传入一个链表
	linklist p;
	while (head != NULL) {//遍历链表
		p = head;//用p记住待释放的结点
		head = head->next;//head结点移动
		free(p);//释放
	}
}

遍历输出数据:

如码:

void print(linklist head) {
	linklist p = head;
	while (p != NULL) {
		printf("%d ", p->data);//输出
		p = p->next;//移动
	}
}

单链表查找并删除结点:

查找结点核心代码:

while (p != NULL && p->data != x) {
	p=p->next //没结束或不是要找的x就继续遍历
}

删除结点核心代码:

//第一种,删除第一个结点:
head = p->next;
free(p);
//第二种,非首结点(pre为p的前驱结点)
pre->next = p->next;
free(p);

查找并删除结点函数:

linklist deleteList(linklist head, int x) {//x为要删除的结点的数据值
	linklist pre = NULL, p = head;
	while (p != NULL && p->data != x) {
		pre = p;//用pre及时记录p的前驱结点
		p = p->next;
	}
	if (p) {
		if (pre == NULL) {//如果删除的是首结点
			head = head->next;
		}
		else {
			pre->next = p->next;
		}
		free(p);
	}
	return head;
}

例题:

如题:

 分析:

直接通过单链表建立函数,最大最小值删除函数,输出答案函数解题:

如码:

#include <stdio.h>
#include <stdlib.h>
int maxx = -1000, minn = 1000;//记录最高最低分
struct node {
	int data;
	struct node* next;
};
typedef struct node linknode;
typedef linknode* linklist;
linklist scan()/*建立链表*/
{
	linklist head = NULL, tail = NULL, p;
	int x;
	printf("输入各个评委的打分 输出-1结束\n");
	scanf("%d", &x);
	if (x != -1) {//时刻记录最高最低分
		maxx = x > maxx ? x : maxx;
		minn = x < minn ? x : minn;
	}
	while (x != -1) {
		p = (linklist)malloc(sizeof(linknode));
		p->data = x;
		if (head == NULL)
			head = tail = p;
		else {
			tail->next = p;
			tail = p;
		}
		scanf("%d", &x);
		if (x != -1) {//时刻记录最高最低分
			maxx = x > maxx ? x : maxx;
			minn = x < minn ? x : minn;
		}
	}
	if (tail != NULL) tail->next = NULL;
	return head;//返回建立完的链表
}
linklist deletemax(linklist head) {/*删除最高分*/
	linklist pre, p;
	pre = NULL;
	p = head;
	while (p != NULL && p->data != maxx) {//找到最高分所在的节点
		pre = p;
		p = p->next;
	}
	if (pre == NULL) head = head->next;
	else pre->next = p->next;
	free(p);
	return head;//返回修改后的链表
}
linklist deletemin(linklist head) {/*删除最低分*/
	linklist pre, p;
	pre = NULL;
	p = head;
	while (p != NULL && p->data != minn) {//找到最低分所在的节点
		pre = p;
		p = p->next;
	}
	if (pre == NULL) head = head->next;
	else pre->next = p->next;
	free(p);
	return head;//返回修改后的链表
}
void print(linklist head) {/*输出答案*/
	linklist p = head;
	double sum = 0; double geshu = 0;
	printf("New list:\n");
	while (p != NULL) {
		printf("%d ", p->data);
		sum += p->data;
		geshu++;
		p = p->next;
	}
	printf("\n");
	printf("最终得分是:%.2lf\n", (sum / geshu));
}
void freeLinklist(linklist head) {/*释放内存*/
	linklist p;
	while (head != NULL) {
		p = head;
		head = head->next;
		free(p);
	}
}
int main()
{
	linklist head = scan();//建立单链表
	head = deletemax(head);//删除最高分
	head = deletemin(head);//删除最低分
	print(head);//输出答案
	freeLinklist(head);//释放内存
	return 0;
}

输出情况:

感谢阅读!!!

 “ Ctrl AC!一起 AC!”

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ctrl AC

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

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

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

打赏作者

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

抵扣说明:

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

余额充值