????????关注后回复 “进群” ,拉你进程序员交流群????????

作者丨写代码的牛顿

来源丨编程学习总站

01

单链表结点定义以及操作函数声明

我们知道在C语言里数组可以存储大量相同数据类型的数据,但是数组有个很明显的缺点就是大小固定不够灵活,我们必须知道数据量的大小,很多时候我们并不知道数据量有多少,这个时候数组就明显不适合了。现在需要一种数据结构能灵活存储数据,随时可以存储和删除数据,而且并不需要估计数据量多少。单链表能满足我们的需求,且是一种最简单的链状数据结构。下面我们看一下链表结点是如何定义的。

typedef struct list {struct list* next;int data;
}list_t;

这里我们通过typedef自定义一个结构体数据类型list_t,在list_t里我们定义了一个next指针用于指向下一个结点,这里我要说明一下为什么next指针要定义成struct list类型,而且为什么可以这样用,后面的数据结构学习,我们会大量这样使用。在我们定义next指针之前已经声明了结构体list,相当于做了前置声明,既然已经声明了,那么自然就可以使用了。
现在我们声明一些链表操作函数,插入、删除、查找某个位置的结点、删除某个结点、销毁链表,打印链表结点数据。

extern list_t *new_list_node(int data); //新建一个结点
extern list_t *list_add(list_t *list, int data); //头插法插入一个结点
extern void list_destroy(list_t *list); //销毁链表
extern list_t *list_delete_node(list_t *list, list_t *node); //删除某个链表
extern list_t *list_delete(list_t *list, int data); //删除某个位置的结点
extern list_t *list_index_of(list_t *list, int index); //查找某个位置的结点
extern void list_print(list_t *list); //打印链表数据

可以看到很多链表函数我们都会返回一个list_t类型指针,其实这个是链表头结点。操作函数如何实现主要看个人风格,有的人喜欢传入二级指针形参达到修改链表的目的,当然也可以。

02

单链表操作函数实现

  • 新建链表结点

list_t* new_list_node(int data) {list_t* node = (list_t*)malloc(sizeof(list_t));if (!node) {return NULL;}node->data = data;node->next = NULL;return node;
}

在链表结点函数定义里,我们通过malloc申请一块结点内存,接下来就是对结点进行初始化,next指针一定要置为NULL。

  • 链表插入结点

list_t *list_add(list_t* list, int data) {if (!list) {return NULL;}list_t* node = new_list_node(data);node->next = list; //采用头插法插入结点return node;
}

每插入一个链表结点都要申请一块结点内存,并将数据存储在结点里。在这里我们采用头插法将结点插入链表,头插法则是每次从链表头部插入一个结点,只需要O(1)时间复杂度。每插入一个新结点node都需要将node的next指针指向链表头结点,那么node就变成了链表头结点,最后将node结点返回作为链表头。

  • 销毁链表

void list_destroy(list_t* list) {//空链表无需销毁if (!list) {return;}list_t* head = list; //将头结点保存到headwhile (head != NULL) {list = list->next; //循环遍历链表free(head); //释放结点内存head = NULL;head = list; //head重新保存链表头结点(这里很关键!!!)}
}

销毁操作一定要用另外一个指针保存即将被销毁的结点,然后链表头结点不断的遍历。

  • 删除指定结点

list_t *list_delete_node(list_t* list, list_t* node) {if (!list) {return NULL;}if (!node) {return list;}list_t* head = list;list_t* prev = NULL;while (list != NULL && list != node) {prev = list; //保存目标结点的前一个结点list = list->next;}    //找不到目标结点if(list == NULL){return head;}//目标结点是头结点if (list == head) {head = head->next; //目标结点的下一个结点是头结点free(list); //销毁目标结点list = NULL;}//目标结点是尾结点,尾结点的next指针是NULLelse if(list->next == NULL){prev->next = NULL; //目标结点的前一个结点next指针置为NULLfree(list); //释放目标结点list = NULL;}//目标结点是中间结点else {prev->next = list->next; //目标结点的前一个结点的next指针指向目标结点的下一个结点list->next = NULL;free(list); //释放目标结点list = NULL;}return head; //返回链表头结点
}

删除结点时有几个需要注意的地方:

  1. 需要一个指针保存目标结点的上一个结点

  2. 需要充分考虑目标结点是头结点还是尾结点还是链表的中间结点。

  • 删除指定值的结点

list_t *list_delete(list_t* list, int data) {if (!list) {return NULL;}list_t* head = list;list_t* prev = NULL;//遍历查找目标结点while (list != NULL && list->data != data) {prev = list; //保存目标结点的前一个结点list = list->next;}//找不到目标结点if (!list) {return  head;}//目标结点是头结点if (list == head) {head = head->next; //原头结点的下一个结点变为新的头结点free(list); //释放目标结点list = NULL;}//目标结点是尾部结点else if (list->next == NULL) {prev->next = NULL; //目标结点的前一个结点next指针置为NULLfree(list); //销毁目标结点list = NULL;}//目标结点是中间结点else {prev->next = list->next; //目标结点的前一个结点的next指针指向目标结点的下一个结点free(list);list = NULL;}return head; //返回头结点
}
  • 查找指定位置的结点

list_t *list_index_of(list_t* list, int index) {if (!list || index < 0) {return NULL;}int list_index = 0;while (list_index < index) {list_index++;list = list->next;}return list;
}
  • 打印链表结点数据

void list_print(list_t* list) {if (list == NULL) {return;}while (list != NULL) {printf("%d, ", list->data);list = list->next;}printf("\n");
}

最后我们写一个小程序验证我们的链表实现是否正确

#include <stdio.h>
#include <stdlib.h>#include "list.h"int main(int argc, char* argv[]) {list_t* list = new_list_node(1); //新建链表头结点//插入结点list = list_add(list, 2);list = list_add(list, 5);list = list_add(list, 6);list = list_add(list, 10);list = list_add(list, 16);list = list_add(list, 15);list_print(list); //打印链表list = list_delete(list, 10);list_print(list); //打印链表list_t* node = list_index_of(list, 3); //找到索引3的链表结点(索引从0开始)printf("node->data = %d\n", node->data);list = list_delete_node(list, node); //删除结点list_print(list); //打印链表list_destroy(list); //销毁链表list = NULL;return 0;
}

编译运行输出:

15, 16, 10, 6, 5, 2, 1,
15, 16, 6, 5, 2, 1,
node->data = 5
15, 16, 6, 2, 1,

链表实现代码完全正确。

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击????卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

数据结构与算法篇-单链表相关推荐

  1. 数据结构与算法:单链表(利用万能指针实现对任意类型数据进行操作)

    前言 C语言的指针真的很强大,万能指针更强大,可以指向任意类型的数据.在上篇博客 数据结构与算法:单链表(超详细实现)中用C语言实现了单链表的相关算法,不过却有局限性 只能针对某一种数据类型还是不够强 ...

  2. 数据结构与算法之单链表

    数据结构与算法之单链表 //链表的实现/*实现单链表的 构建.数据添加.数据删除(返回元素所在位置).数据查找(返回元素所在的位置)的算法设计:*/ //链表的实现/*实现单链表的 构建.数据添加.数 ...

  3. 数据结构与算法:单链表(超详细实现)

    实现算法预览 这次博主写的单链表主要实现了以下算法.所有功能可进行循环运行测试.欢迎各位指正. LinkList.h #pragma once #ifndef __LINKLIST_H__ #defi ...

  4. 数据结构与算法之单链表(1)

    在说头插法建立单链表之前,先补充几个知识点: 用typedef定义类型:意思就是可以用typedef声明新的类型名来代替已有的类型名. 例如: typedef struct { int month; ...

  5. (数据结构与算法)单链表与双链表增删改查的实现。

    文章目录 链表介绍 1. 单链表应用实例 1.1 实现思路 1.2 代码实现 2.单链表常见面试题 2.1 求单链表中有效节点的个数 2.2 查找单链表中倒数第K个节点 2.3 单链表的反转 2.4 ...

  6. 数据结构和算法之单链表

    package com.company;import java.util.Stack;/*** @author:抱着鱼睡觉的喵喵* @date:2021/2/4* @description:*/ pu ...

  7. java宋江,Java编程内功-数据结构与算法「单链表」,

    package com.structures.linkedlist; public class SingleLinkedListDemo { public static void main(Strin ...

  8. 【数据结构与算法】单链表的Java实现

    链表 数据结构的逻辑表示有4种类型: 集合:元素之间无关 线性:元素之间1->1的关系 树:元素之间1->many的关系 图:元素之间many->many的关系 最基础的线性结构的简 ...

  9. 【数据结构与算法】单链表的插入和删除

最新文章

  1. 微软亚洲研究院发布“人立方关系搜索”
  2. 腾讯大佬和你闲聊图像分割这件事儿
  3. terminateActivity
  4. opencore0.6.4_iOS 13.4/iPadOS 13.4正式版发布:iCloud支持文件夹共享
  5. 基于Protues的Arduino学习笔记01-Arduino UNO实验板设计
  6. yolobile 道路损坏检测实战
  7. shell倒数第三位增加字符_shell中常用的变量处理、字符串操作(之三)
  8. [AE] ArcGIS Engine处理Landsat8数据
  9. monkey入门研究
  10. 通用数据权限的设计思路
  11. 《Python助力交通》公众号说明
  12. 大写字母转换成小写字母
  13. 图文模态交互 | CLIP + GAN = ?
  14. 如何在本地电脑上搭建AI人工智能绘画工具Stable Diffusion
  15. 虚拟机无法玩腾讯游戏该怎么办
  16. 辅助 Excel 的数据计算 add-ins
  17. win8.1 64位专业版,安装内存8G,显示3.25G可用,怎么办?
  18. 为PLOG增加了三套模板
  19. 腾讯云提示有木马文件事件通知 该如何处理?
  20. linux远程windows无法输入,XRDP在Windows下用远程桌面连接,键盘失效有关问题

热门文章

  1. Mac版 Photoshop 2021 绿色版 安装记录
  2. 炫酷可视化教程 Cufflinks 来啦!!!
  3. C++:有限差分法求解随时间变化 平流方程 ut = - c * ux 在一个空间维度上,与 恒定速度,使用Lax-Wendroff方法作为时间导数(附完整源码)
  4. SAP ECC 6.0 下载以及安装
  5. 09、IO流—File类与IO流
  6. word- 图片显示不全/错位
  7. 词性、句法分析、依存关系的符号解释
  8. JavaScript——问卷星自动填写
  9. c++ vector的底层实现
  10. 利用python开发的flappy bird 游戏