目录

前言

单链表的分类

有表头单链表

一、create()创建链表,后面产生的结构体将放在表头后面

二、newNote()创建节点,读取用户输入的记录,生成结构体数据

三、insert()从表头插入新的数据,可用于添加信息的功能。

四、query()通过接收用户的编号来查找链表中对应的记录,但只能返回第一个编号相同的记录

五、query a record()查找函数,可用于查找信息功能

六、delete()用于删除第一个与编号相同的记录

八、sort()按编号排序,用于信息排序,经典的冒泡排序法

九、display()用于信息显示

十、Reverse()链表逆置

完整代码展示


前言

在我们学习C语言基础的过程中,指针和链表一直是新手的两大拦路虎。在大学的程序语言课程设计中,我们在设计系统时可能会用到链表或者结构体数组。今天,我想为大家梳理一下关于单链表的使用。本文章需要读者先行理解C语言的结构体和结构体中next的使用。

注:我所使用的是vs2019,部分代码可能在其他编译器中会报错。

单链表的分类

在我理解中,单链表分为两类,一种是有表头单链表,一种是无表头单链表。本章我先来帮助大家理解有表头单链表。

结构体框架

struct Structure //为了方便大家理解char类型和int类型在使用上的区别,我特地分别设置了两个变量
{char num[4];//编号int score;//分数char name[10];//姓名int room;//房间号struct Structure* next;
};

有表头单链表

有表头单链表,顾名思义,就是创建的链表中表头数据为NULL,next直接指向下一结构体。它包含的基础功能有:添加信息,查找信息,删除信息,信息排序,文件操作,信息显示。文件操作功能我暂且放在下一章讲解。

下面,我来讲解使用有表头单链表需要使用到的函数:

一、create()创建链表,后面产生的结构体将放在表头后面

struct Structure* create()//创建有表头链表(不存数据)
{struct Structure* head = (struct Structure*)malloc(sizeof(struct Structure));//产生变量head->next = NULL;//初始化变量return head;
}

我们需要在主函数main中编写 struct Structure* head = create();  这样一个链表的表头就形成了。

二、newNote()创建节点,读取用户输入的记录,生成结构体数据

struct Structure* newNote()//创建节点
{struct Structure* p = (struct Structure*)malloc(sizeof(struct Structure));scanf_s("%s%d%s%d", p->num, 4, &p->score, p->name, 10, &p->room);p->next = NULL;return p;
}

scanf_s代码解释:              //  scanf_s("%s%d%s%d", p->num, 4, &p->score, p->name, 10, &p->room);

1.代码解读:num和name均为char类型的数组变量,在取址时可以不用添加“&”,后面跟着的4,10为可读取数据的长度。score和room为int类型变量,需添加“&”读取地址

2.这是vs新版本中为了保证系统的安全,添加了检验机制。

3.它与scanf的区别在于,读取字符串时可以确定读取的长度,当输入字符串长度过长时可以直接对该变量赋值为空,且不影响后续数据的读取。若输入数据为123456 78 张三 101,则存储的数据为:num=""   score=78   name="张三"  room=101   。

函数解读,创建一个结构体,并存储用户输入数据,并将该结构体返回。

三、insert()从表头插入新的数据,可用于添加信息的功能。

void insert(struct Structure* head)//调用创建节点导入数据并从表头插入
{int n;//用于读取用户输入的记录个数printf("请输入你要录入的学生个数:");scanf_s("%d", &n);for (;  n < 1; n--){printf("请输入数据\n");//也可以定义变量i来提示用户当前输入的记录条数struct Structure* node = newNote();node->next = head->next;head->next = node;}
}

将用户输入的记录一个个从表头插入链表中。

四、query()通过接收用户的编号来查找链表中对应的记录,但只能返回第一个编号相同的记录

Structure* Query(Structure* head, char* num)//查找编号,有则返回对应结构体,否则返回空链表
{Structure* p;p = head;while (p != NULL){if (strcmp(num, p->num) == 0) return p;p = p->next;}return NULL;
}

本函数中使用了strcmp()函数,需使用头文件#include<string.h>。常用于比较两个字符串的大小,当两种相同时则返回数值0。

本函数从表头开始查找,编号相同则返回,直到查找到链表尾步为止,若无对应编号则返回空值。

常被query a record查找函数和delete删除函数调用。

五、query a record()查找函数,可用于查找信息功能

void Query_a_record(Structure* head)//接收查找反馈并展示结果
{char s[4];Structure* p;printf("请输入一个要查找的编号\t");scanf_s("%s", s, 4);getchar();p = Query(head, s);if (p != NULL){printf("%s %d %s %d", p->num, p->score, p->name, p->room);system("pause");}else{printf("找不到对应的编号!\t\t");system("pause");}
}

调用query查找函数,分两种情况,若查找到记录则显示;若返回值为空则链表没有该编号。

缺点:无法判断链表是否存储数据

六、delete()用于删除第一个与编号相同的记录

Telephone* Delete(Telephone* head, char* num)//接收数据,并删除编号相同的记录
{Telephone* p1, * p2=NULL;p1 = head;while ((strcmp(num, p1->num) != 0) && (p1->next != NULL)){p2 = p1; p1 = p1->next;}if (strcmp(num, p1->num) == 0){if (p1 == head) head = p1->next;else p2->next = p1->next;free(p1);}return head;
}

用于接收来自delete a record删除函数传递的编号,然后删除第一个与之编号相同的记录

缺点:只能删除一个

七、delete a record()用于删除信息功能,删除查询的记录

Structure* Delete_a_record(Structure* head)//传递要删除的记录编号,并选择是否删除
{char s[4];printf("请输入你要删除的编号:\t");scanf_s("%s", s, 4);getchar();if (Query(head, s) != NULL){       head = Delete(head, s);printf("编号为%s的记录已删除", s);system("pause");}else{printf("编号为%s的记录未查询到", s);system("pause");}return head;
}

通过调用query查找函数来确定编号是否存在,然后调用delete删除函数来删除记录。

八、sort()按编号排序,用于信息排序,经典的冒泡排序法

void sort(struct Structure* head)//排序
{int i, j, n = 0;Structure t, * p = head, * p1, * p2;while (p != NULL)//统计结构体数量{n++;p = p->next;}p2 = head;for (i = 0; i < n - 1; i++){p1 = p2->next;p = p2;for (j = i + 1; j < n; j++){if (strcmp(p1->num, p->num) < 0) p = p1;p1 = p1->next;}if (p != p2){strcpy(t.num, p2->num);strcpy(t.name, p2->name);t.room = p2->room;t.score = p2->score;strcpy(p2->num, p->num);strcpy(p2->name, p->name);p2->room = p->room;p2->score = p->score;strcpy(p->num, t.num);strcpy(p->name, t.name);p->room = t.room;p->score = t.score;}p2 = p2->next;}printf("升序排列操作已完成!\t");system("pause");
}

t是结构体变量,是交换的载体。而p1,p2是结构体指针。所以在调用结构体成员时,t使用".",p1使用"->"。

九、display()用于信息显示

void Display(Structure* head)//显示记录
{Structure* p = head;printf("编号\t\t成绩\t\t姓名\t\t教室\n");p = p->next;//跳过表头while (p != NULL){printf("%s\t\t%d\t\t%s\t\t%d\n", p->num, p->score, p->name, p->room);p = p->next;}system("pause");
}

十、Reverse()链表逆置

不知道怎么说,读者可以通过画图自行体会

Structure* Reverse(Structure* head)
{Structure* p1, * p2, *p3;p3 = head->next;p1 = p3->next;p3->next = NULL;while (p1 != NULL){p2 = p1; p1 = p1->next;p2->next = p3; p3 = p2;}head->next = p3;return head;
}

完整代码展示

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//为了方便大家理解char类型和int类型在使用上的区别,我特地分别设置了两个变量
struct Structure
{char num[4];//编号int score;//分数char name[10];//姓名int room;//房间号struct Structure* next;
};
//创建有表头链表(不存数据)
struct Structure* create()
{struct Structure* head = (struct Structure*)malloc(sizeof(struct Structure));//产生变量head->next = NULL;//初始化变量return head;
}
//创建节点
struct Structure* newNote()
{struct Structure* p = (struct Structure*)malloc(sizeof(struct Structure));scanf_s("%s%d%s%d", p->num, 4, &p->score, p->name, 10, &p->room);p->next = NULL;return p;
}
//调用创建节点导入数据并从表头插入
void insert(struct Structure* head)
{int n;//用于读取用户输入的记录个数printf("请输入你要录入的学生个数:");scanf_s("%d", &n);for (;  n > 0; n--){printf("请输入数据\n");//也可以定义变量i来提示用户当前输入的记录条数struct Structure* node = newNote();node->next = head->next;head->next = node;}
}
//查找编号,有则返回对应结构体,否则返回空链表
Structure* Query(Structure* head, char* num)
{Structure* p;p = head;while (p != NULL){if (strcmp(num, p->num) == 0) return p;p = p->next;}return NULL;
}
//接收查找反馈并展示结果
void Query_a_record(Structure* head)//接收查找反馈并展示结果
{char s[4];Structure* p;printf("请输入一个要查找的编号\t");scanf_s("%s", s, 4);getchar();p = Query(head, s);if (p != NULL){printf("%s %d %s %d", p->num, p->score, p->name, p->room);system("pause");}else{printf("找不到对应的编号!\t\t");system("pause");}
}
//接收数据,并删除编号相同的记录
Structure* Delete(Structure* head, char* num)
{Structure* p1, * p2 = NULL;p1 = head;while ((strcmp(num, p1->num) != 0) && (p1->next != NULL)){p2 = p1; p1 = p1->next;}if (strcmp(num, p1->num) == 0){if (p1 == head) head = p1->next;else p2->next = p1->next;free(p1);}return head;
}
//传递要删除的记录编号,并选择是否删除
Structure* Delete_a_record(Structure* head)
{char s[4];printf("请输入你要删除的编号:\t");scanf_s("%s", s, 4);getchar();if (Query(head, s) != NULL){       head = Delete(head, s);printf("编号为%s的记录已删除", s);system("pause");}else{printf("编号为%s的记录未查询到", s);system("pause");}return head;
}
//排序
void sort(struct Structure* head)
{int i, j, n = 0;Structure t, * p = head, * p1, * p2;while (p != NULL)//统计结构体数量{n++;p = p->next;}p2 = head;for (i = 0; i < n - 1; i++){p1 = p2->next;p = p2;for (j = i + 1; j < n; j++){if (strcmp(p1->num, p->num) < 0) p = p1;p1 = p1->next;}if (p != p2){strcpy(t.num, p2->num);strcpy(t.name, p2->name);t.room = p2->room;t.score = p2->score;strcpy(p2->num, p->num);strcpy(p2->name, p->name);p2->room = p->room;p2->score = p->score;strcpy(p->num, t.num);strcpy(p->name, t.name);p->room = t.room;p->score = t.score;}p2 = p2->next;}printf("升序排列操作已完成!\t");system("pause");
}
//显示记录
void Display(Structure* head)
{Structure* p = head;printf("编号\t\t成绩\t\t姓名\t\t教室\n");p = p->next;//跳过表头while (p != NULL){printf("%s\t\t%d\t\t%s\t\t%d\n", p->num, p->score, p->name, p->room);p = p->next;}system("pause");
}
void Display_Main_Menu()
{printf("1.添加信息\n");printf("2.删除信息\n");printf("3.查找信息\n");printf("4.排序信息\n");printf("5.显示信息\n");printf("0.退出系统\n");
}
int main()
{int choose, b;struct Structure* head = create();while (1){Display_Main_Menu();scanf_s("%d", &choose);switch (choose){case 1:insert(head);system("cls");break;case 2:Delete_a_record(head);system("cls");break;case 3:Query_a_record(head);system("cls");break;case 4:sort(head);system("cls");break;case 5:Display(head);system("cls");break;case 0:goto loop;default:printf("\t请输入选项0—9!\n");system("pause");}}
loop:printf("感谢本次使用成绩处理系统\n");system("pause");
}

C语言单链表讲解(上):有表头链表的使用相关推荐

  1. 数据结构——链表讲解(1)

    作者:几冬雪来 时间:2023年3月3日 内容:数据结构链表讲解 目录 前言: 链表的概念: 1.为什么要有链表: 2.链表的运行原理: 3.链表的形态多少: 4.单链表的代码书写: 1.创建文件: ...

  2. c语言单链表倒置(附原理讲解)

    c语言单链表倒置 今天博主,讲一个单链表倒置的例子,事实上 话不多说,我们直接上代码,待会会给大家讲解倒置算法实现原理 #include<stdio.h> #include<stdl ...

  3. 链式存储【C语言单链表】

    文章目录 单链表 单链表的结构 需要的头文件 申请节点 单链表尾插 单链表头插 单链表尾删 单链表头删 单链表查找 单链表在(pos之前/pos之后)插入数据 单链表删除(pos/pos之后)数据 单 ...

  4. c语言单链表设计报告,单链表实验报告

    <数据结构>实验报告二 分校: 学号: 日期: 班级: 姓名: 程序名: L2311.CPP 一.上机实验的问题和要求: 单链表的查找.插入与删除.设计算法,实现线性结构上的单链表的产生以 ...

  5. C语言单链表基本操作总结

    C语言单链表基本操作     本文是参考他人实现的C语言单链表,对多篇博文整理的结果,仅作为学习笔记.文末有参考出处. 1.单链表定义 链表是通过一组任意的存储单元来存储线性表中的数据元素,这些存储单 ...

  6. C语言单链表实现19个功能完全详解

    #include "stdafx.h" #include "stdio.h" #include <stdlib.h> #include " ...

  7. 数据结构中单链表的存储c语言,单链表一 - 数据结构与算法教程 - C语言网

    1. 单链表概念&设计 单链表是一种链式存取的数据结构,,链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指 ...

  8. C语言一趟冒泡交换最小值,C语言单链表冒泡排序为啥以下代码实现不了?

    struct node *sort(struct node *head)/*排序*/ { struct node *p,*q; struct node *temp; for(p=head;p!=NUL ...

  9. c语言单链表功能,[数据结构]单链表(C语言)的各种功能

    06-03阅读200,000 + 链表是一种常见的基本数据结构,在此充分利用了结构指针. 链表可以动态存储和分配,即链表是一个功能非常强大的数组. 他可以在节点中定义多种数据类型,并可以根据需要随意添 ...

最新文章

  1. 服务器状态监控之二软硬件环境介绍
  2. 罗永浩直播间再回应直播售假:全方位整改 成立质控实验室
  3. java基础环境搭建_java基础环境搭建
  4. ajax调用后台Datatable
  5. Eclipse 4.7(Oxygen)安装Tomcat Plugin 后没有小猫图标解决方法
  6. VS2017下载安装
  7. c++哈利波特编程代码
  8. 腾讯 AI Lab 2021 年度回顾
  9. 多线程启动停止暂停继续
  10. 替代A4988的微型打印机驱动TMI8421国产电机驱动芯片
  11. 硬件工程师入门基础知识(一)基础元器件认识(一)
  12. 【SQL武林秘籍】零基础带你快速上手SQL语言
  13. ANSYS Workbench中多场耦合下不同模块间的信息共享设置
  14. pbx_extension_helper: No application ‘Macro‘ for extension (from-internal, h, 1)
  15. 小米路由hd php,详谈小米路由器Pro / HD,俩都是…
  16. XNA入门/框架介绍
  17. python内置函数返回序列中最大元素_Python 内置函数 ____________ 用来返回序列中的最大元素。_学小易找答案...
  18. java文件名加时间戳_Java处理文件名加时间戳
  19. 戴维南定理(Thevenin‘s theorem)
  20. Trace Related

热门文章

  1. 醉林疯的OJ 1063: 最大公约与最小公倍
  2. 在线支付(易宝支付)
  3. 4.2.7. Aggregate Expressions
  4. 南京大学2020计算机考研分数线,南京大学2020考研复试分数线已公布
  5. 显示thread 1:signal SIGABRT 错误
  6. 批量修改文件名,图文教学,2分钟简单学会
  7. 异常检测综述(Anomaly Detection: A Survey)
  8. oauth2单点登录总结
  9. 《佛密诸事》第十一章:解读大悲咒
  10. layui省市县三级联动,如何设置select选择时,值为省市县code码