听黑马程序员教程《基础数据结构和算法 (C版本)》,照着老师所讲抄的,

视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1

喜欢的朋友可以去看看。

02 单向链表

  1. #include<stdio.h >
  2. #include<stdlib.h>
  3. #include<string.h>
  4.  
  5. // 用户自定义数据
  6. typedef struct Student{
  7. int id; // 学号
  8. char name[32]; // 姓名
  9. char classs[32]; // 班级
  10. int ch,ma,en; // 语、数、外、总分
  11. }st;
  12.  
  13. // 链表结点
  14. typedef struct LINKNODE{
  15. //int i_data; // 这样写就写死了,只能放int数据了,
  16. void* data; // void* 是无类型指针,可以指向任何类型的数据。
  17. struct LINKNODE* next;
  18. }LinkNode;
  19.  
  20. // 链表结构体
  21. typedef struct LINKLIST{
  22. LinkNode* head; // 头结点
  23. int size; // 链表节点数
  24. // 要像动态数组一样需要内存容量吗?不需要, 没有容量概念。
  25. }LinkList;
  26.  
  27. // 打印函数指针
  28. typedef void(*PRINTLINKNODE)(void*);
  29.  
  30. // -----------------------------------------------------------------------------
  31. // 下面函数,就是针对上面链表结构体和结点的操作。
  32. // -----------------------------------------------------------------------------
  33.  
  34. // 初始化链表 ,返回一个链表结构体
  35. LinkList* Init_LinkList();
  36.  
  37. // 指定位置插入。参数:所插入的链表,位置,值
  38. void Insert_LinkList(LinkList* list,int pos,void* data);
  39.  
  40. // 删除指定位置的值。 参数:链表,位置
  41. void RemoveByPos_LinkLIst(LinkList* list,int pos);
  42.  
  43. // 获得链表的长度(结点数量)
  44. int Size_LinkList(LinkList* list);
  45.  
  46. // 根据值,查找位置
  47. int Find_LinkList(LinkList* list,void* data);
  48.  
  49. // 返回第一个节点
  50. void* Front_LinkList(LinkList* list);
  51.  
  52. // 打印链表结点
  53. void Print_LinkList(LinkList* list,PRINTLINKNODE print);
  54.  
  55. // 释放内存
  56. void FreeSpace_LinkList(LinkList* list);
  57.  
  58. // ----------------------------------- main() --------------------
  59.  
  60. // 打印函数
  61. void MyPrint(void* data){
  62. st* p = (st*)data;
  63. printf("学号:%d\t姓名:%s\t班级:%s\t语文%d\t数学%d\t英语%d\t总分%d\n",
  64. p->id,p->name,p->classs,p->ch,p->ma,p->en,p->ch+p->ma+p->en);
  65. }
  66. int main(){
  67. printf("好好学习,天天向上~!(单向链表20220603)\n\n");
  68.  
  69. // 创建链表
  70. LinkList* stList = Init_LinkList();
  71.  
  72. // 创建数据
  73. st st1 = {2001,"宗宗","364班",100,100,100};
  74. st st2 = {2002,"艳艳","364班",99,88,59};
  75. st st3 = {2003,"发发","364班",88,77,66};
  76. st st4 = {2004,"小小","364班",58,57,55};
  77. st st5 = {2005,"小五","364班",58,57,55};
  78.  
  79. // 插入数据
  80. Insert_LinkList(stList,0,&st1);
  81. Insert_LinkList(stList,0,&st2);
  82. Insert_LinkList(stList,0,&st3);
  83. Insert_LinkList(stList,0,&st4);
  84. Insert_LinkList(stList,0,&st5);
  85.  
  86. // 打印
  87. Print_LinkList(stList,MyPrint);
  88.  
  89. printf("\n删除第3个节点\n");
  90. RemoveByPos_LinkLIst(stList,3);
  91. // 打印
  92. Print_LinkList(stList,MyPrint);
  93.  
  94. printf("\n返回第一个节点\n");
  95. // 返回的是void* 类型,要转换成st*类型
  96. st* ret = (st*)Front_LinkList(stList);
  97. printf("学号:%d\t姓名:%s\t班级:%s\t语文%d\t数学%d\t英语%d\t总分%d\n",
  98. ret->id,ret->name,ret->classs,ret->ch,ret->ma,ret->en,ret->ch+ret->ma+ret->en);
  99.  
  100. // 销毁释放
  101. FreeSpace_LinkList(stList);
  102. return 0;
  103. }
  104.  
  105. // -----------------------------------------------------------------------------
  106. // 下面函数,就是针对上面链表结构体和结点的操作。
  107. // -----------------------------------------------------------------------------
  108.  
  109. // 初始化链表 ,返回一个链表结构体
  110. LinkList* Init_LinkList(){
  111. LinkList* list = (LinkList*)malloc(sizeof(LinkList));
  112. list->size = 0;
  113. // 添加头节点,头节点不保存数据
  114. list->head = (LinkNode*)malloc(sizeof(LinkNode));
  115. list->head->next = NULL; // 头结点初始化一下
  116.  
  117. return list;
  118. }
  119.  
  120. // 指定位置插入。参数:所插入的链表,位置,值(是数据指针)
  121. void Insert_LinkList(LinkList* list,int pos,void* data){
  122.  
  123. // 判断检查参数
  124. if(list==NULL){
  125. return;
  126. }
  127. if(data==NULL){
  128. return;
  129. }
  130. if(pos<0 || pos > list->size){ // 友好判断,如果位置pos越界,由插入到尾部
  131. pos = list->size;
  132. }
  133.  
  134. // 创建新的节点
  135. LinkNode* newNode = (LinkNode*)malloc(sizeof(LinkNode));
  136. newNode->data = data; // 新节点赋值
  137.  
  138. // 找结点
  139. LinkNode* pCurrent = list->head; // 辅助指针,用于找当前节点(插入位置的前一个节点)
  140. int i;
  141. for(i=0;i<pos;i++){ // 通过循环找到插入位置的前一个节点
  142. pCurrent = pCurrent->next;
  143. }
  144. // 插入
  145. newNode->next = pCurrent->next;
  146. pCurrent->next = newNode;
  147.  
  148. list->size++; // 更新节点数量的记录。
  149.  
  150. }
  151.  
  152. // 删除指定位置的值。 参数:链表,位置
  153. void RemoveByPos_LinkLIst(LinkList* list,int pos){
  154. // 判断检查参数
  155. if(list==NULL){
  156. return;
  157. }
  158. if(pos<0 || pos >= list->size){
  159. //pos = list->size; // 这里就不能友好判断了,
  160. return; // 指定位置不存在,直接返回。
  161. }
  162.  
  163. // 删除
  164. // 找结点
  165. LinkNode* pCurrent = list->head; // 辅助指针,用于找当前节点(删除节点的前一个节点)
  166. int i;
  167. for(i=0;i<pos;i++){ // 通过循环找到要删除结点的前一个节点
  168. pCurrent = pCurrent->next;
  169. }
  170. // 删除(先缓存要删除的节点)
  171. //pCurrent->next = pCurrent->next->next;
  172. //free(pCurrent->next);
  173. LinkNode* pDel = pCurrent->next;
  174. pCurrent->next = pDel->next;
  175. free(pDel);
  176. list->size--; // 更新链表节点数量
  177.  
  178. }
  179.  
  180. // 获得链表的长度(结点数量)
  181. int Size_LinkList(LinkList* list){
  182.  
  183. return -1;
  184. }
  185.  
  186. // 根据地址,查找位置,void* data 是地址(指针),不是值。
  187. int Find_LinkList(LinkList* list,void* data){
  188. // 判断检查参数
  189. if(list==NULL){
  190. return -1;
  191. }
  192. if(data==NULL){
  193. return -1;
  194. }
  195.  
  196. // 遍列查找节点,从头节点的下一个节点开始找
  197. LinkNode* pCurrent = list->head->next;
  198. int i = 0;
  199. while(pCurrent){
  200. if(pCurrent->data==data){
  201. break;
  202. }
  203. pCurrent = pCurrent->next;
  204. i++;
  205. }
  206.  
  207. return i;
  208. }
  209.  
  210. // 返回第一个节点
  211. void* Front_LinkList(LinkList* list){
  212. return list->head->next->data;
  213. }
  214.  
  215. // 打印链表结点
  216. void Print_LinkList(LinkList* list,PRINTLINKNODE print){
  217. if(list==NULL){
  218. return;
  219. }
  220. // 辅助指针变量
  221. LinkNode* pCurrent = list->head->next;
  222. while(pCurrent){
  223. print(pCurrent->data); // 调用用户函数,传入数据参数
  224. pCurrent = pCurrent->next;
  225. }
  226.  
  227. }
  228.  
  229. // 释放内存
  230. void FreeSpace_LinkList(LinkList* list){
  231. if(list==NULL){
  232. return;
  233. }
  234. // 辅助指针变量
  235. LinkNode* pCurrent = list->head;
  236. while(pCurrent){ // 循环释放节点内存。
  237. LinkNode* pNext = pCurrent->next; // 用指针先记录下一个节点,如果不记录的话,释放内存后就没有了,
  238. free(pCurrent);
  239. pCurrent = pNext;
  240. }
  241. free(list); // 节点内存释放完毕后,再释放链表内存
  242. }

C语言 - 基础数据结构和算法 - 单向链表的更多相关文章

  1. C语言 - 基础数据结构和算法 - 企业链表

    听黑马程序员教程<基础数据结构和算法 (C版本)>,照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友可 ...

  2. C语言- 基础数据结构和算法 - 循环链表

    听黑马程序员教程<基础数据结构和算法 (C版本)>,照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友可 ...

  3. C语言- 基础数据结构和算法 - 栈的顺序存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  4. C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611

    09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...

  5. C语言- 基础数据结构和算法 - 08 栈的应用_就近匹配20220611

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  6. C语言- 基础数据结构和算法 - 队列的顺序存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  7. C语言- 基础数据结构和算法 - 栈的链式存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  8. C语言- 基础数据结构和算法 - 动态数组

    听黑马程序员教程<基础数据结构和算法 (C版本)>,照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友可 ...

  9. JS数据结构与算法--单向链表

    链表结构:链表中每个元素由一个存储元素本身的节点和一个指向下一元素的引用组成.如下所示(手画的,比较丑,懒得用工具画了,嘻嘻) 1.append方法,向链表末尾插入一个节点 2.insert(posi ...

随机推荐

  1. 一像素边框的问题(使不同dpr设备完美显示1px的border)

    问题:不同dpr的屏幕有不同的屋里像素值,而我们css像素的1px由于不同屏幕的渲染会导致宽度并不一样: 例如: dpr为2的retina屏幕是有四个物理像素点(真实屏幕上的点)组成一个逻辑(css) ...

  2. js判断时间格式不能超过30天

    let first = this.data.date //开始时间 let second = e.detail.value //结束时间 var data1 = Date.parse(first.re ...

  3. git clone 遇到的问题

    经常遇到这个问题, 所以今天决定把它记录下来 当使用git clone时,会报Please make sure you have the correct access rights and the r ...

  4. 在 M1 Mac 上开发 .NET MAUI (iOS)

    在 M1 Mac 上开始使用 .NET MAUI 开发 (iOS) 的最简单方法. .NET 多平台应用程序 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动 ...

  5. 安卓记账本开发学习day1

    学习了一些简单的布局与界面设计

  6. v-if 和 v-show 的区别

    1.v-if && v-else && v-else-if <span v-if = "4 > 9">hello</span ...

  7. CoAP调试工具 Mozi.IoT.CoAP

    前言 CoAP是一种类HTTP协议的物联网专用协议,其数据包为人类不可阅读的字节流形式,在开发相关应用的时候往往不能准确的了解数据包的内容.故需要专用的调试工具对数据和通讯进行调试. CoAP协议介绍 ...

  8. oracle split 以及 简单json解析存储过程

    BEGIN; 由于之前工作上需要在oracle中做split功能以及json格分解.然后经过一番google和优化整合,最后整理到一个存储过程包中,易于管理,代码如下: 1.包定义: CREATE O ...

  9. ElasticSearch7.3学习(二十一)----Filter与Query对比、使用explain关键字分析语法

    1.数据准备 首先创建book索引 PUT /book/ { "settings": { "number_of_shards": 1, "number ...

  10. python学习-Day18

    目录 今日内容详细 模块 循环导入问题 判断文件类型 py文件可以被分为两种类型 内置变量 __ name __ 模块的查找顺序 验证先从内存空间中查找 验证再从内置模块中查找 验证sys.path ...