数据结构-顺序表、链表

一、线性表介绍

1、线性结构

在数据元素存在非空有限集中

  • 存在唯一的一个被称为“第一个”的数据元素
  • 存在唯一的一个被称为“最后一个”的数据元素
  • 除了第一个外,集合中每个数据元素都只有一个前趋元素
  • 除了最后一个外,集合中每个数据元素都只有一个后继元素

2、线性表

  • 线性表是一个有$n4个数据元素的有限序列,同一个线性表中的元素必定有相同特性,元素之间存在序偶关系
  • 线性表中的元素个数n(n0)定义为该表的长度,当n=0时称为空表,非空表中每个数据元素都有一个确定的位置(下标)
  • 线性表是一个相当灵活的数据结构,它的长度可以根据需要增长或缩短

二、线性表的顺序的表示和存储:

​ 线性表的存储使用一组连续内存来依次存储线性表中的数据元素。
注意

  1. 要时刻保持元素之间的连续性
  2. 千万不要越界

优点

  1. 支持随机访问
  2. 查找、修改、排序效率比较高
  3. 大块的连续内存不容易产生内存碎片

缺点

  1. 对元素插入、删除时效率很低
  2. 大块内存对内存要求较高

三、线性表的链式表示和存储:

​ 链式存储结构不要求内存位置物理上是连续的,因此元素可以存储在内存的任何位置(可以是连续的,也可以不连续)

​ 元素a[i]a[i + 1]之间的逻辑关系不是依靠相互位置,而是在元素中增加一个一个指向其后继元素的数据项(元素指针),从而表示相互之间的逻辑关系,元素本身的数据+后继元素的地址 组成了存储映像,俗称 节点(node)

typedef struct Node {
  	TYPE val;			//	数据域  
   	struct Node* next;	//	指针域
} Node;

若干个节点通过指针域依次连接起来,形成的线性表结构称为链式表,简称链表,如果指针域中只有一个指向下一个节点的指针,这种链表称为单向链表。

代码实现

单向链表

​ 单向链表中必须有一个指向第一个节点的指针,该指针称为头指针,被它指向的节点称为头节点
​ 头节点可以存储、也可以不存储有效数据,如果不存储有效数据的话,那么头节点只是单纯地作为一个占位节点存在
​ 最后一个节点称为尾节点,尾节点的next指向空(NULL),作为结束标志

1、不带头节点的单向链表

定义:第一个节点中的数据域存储有效数据。
注意

  1. 当需要对单链表的头指针发生修改时,例如头添加、头删除、插入等操作,参数需要传递头指针的地址(二级指针),处理相对麻烦
  2. 当进行删除时,需要获取到待删除节点的前趋节点,但是如果删除的位置刚好是第一个节点,它没有前趋节点,所以需要额外判断处理

代码实现

2、带头节点的单向链表

定义:第一个节点中的数据域不存储有效数据,该头节点只是用于指向第一个有效数据的节点而存在。所以,由于头节点不会因为添加、插入、删除该改变,所以不需要传递二级指针

typedef struct List {
    ListNode* head;		//	永远指向头节点	必须要有
    ListNode* tail;		//	尾指针,可以有 也可以没有
    size_t size;		//	数量 可以有 也可以没有
} List;

注意:尾指针tail,能直接找到最后一个节点,但是在尾删除操作时,发挥不了作用,因为要找尾节点的前趋。

代码实现

四、静态链表

  • 静态链表的节点存储在一段连续内存中,通过节点中称为游标的一个正整数来访问后继节点
typedef StaticNode {
	TYPE data;		//	数据域
	int index;	//	游标
} StaticNode;
  • 在静态链表中进行插入、删除时,只需要修改游标的值即可不需要拷贝内存,也能达到链表的效果
  • 但是也牺牲了随机访问节点的功能,而且链表的优点也有缺失。
  • 是给没有指针的编程语言提供一种操作单链表的方式。

五、循环链表

  • 循环链表的最后一个节点的next不再指向NULL,而是指向头节点。如果是单链表就称为单循环链表
  • 好处是能够通过任意节点可以遍历整个链表

六、双向链表(双向循环链表)

  • 所谓的双向链表就是链表节点中有两个指针域,一个指向前一个节点,叫做前趋指针(prev),另一个指向后一个节点,称为后继指针(next)
  • 因此可以从后往前遍历链表,对于要访问链表后半部的节点的操作效率更高
//	双向链表的节点结构
typedef struct ListNode {
    struct ListNode* prev;		//	前趋
    TYPE data;
    struct ListNode* next;		//	 后继
} ListNode;
  • 在双向链表的基础上,让最后一个节点的next指向头节点,让头节点的prev指向最后一个节点,构成了双向循环链表

代码实现

七、Linux内核链表

  • 在普通的链表中,目前面临无法做到任何类型的数据都可以存储的问题。
  • Linux内核链表是一种通用的双向循环链表,面对通用的问题,Linux内核链表的节点干脆不存储任何数据域,只有指针域,节点只负责串联起每个节点,不负责存储数据。
  • 如果要使用Linux内核链表时,把节点放入到数据中。

目的:根据结构体中某个成员的地址,能够计算出所在结构体的首地址,从而用户在设计Linux内核链表的节点时,不需要一定放在在数据的首位成员,增加可用性


//  计算出结构体type的成员mem所在的地址距离第一个成员位置的字节数           
#define offsetof(type,mem) \
    ((unsigned long)(&(((type*)0)->mem)))


//  根据结构成员mem的地址(ptr) 计算出它所在结构(type)变量的首地址
//  ptr要计算的某个节点的地址  type是ptr所在结构体名 mem是它的结构成员名
#define node_to_obj(ptr,type,mem) \
        ((type*)((char*)ptr - offsetof(type,mem)))

三星的代码
自己实现的代码

八、通用链表

Linux内核链表虽然设计很巧妙,但是不利于初学者使用,另一种通用的设计思路是借助void *的兼容性,来设计一种链表,称为通用链表,这种链表还需要借助回调函数。

//	定义了一个函数指针变量
返回值 (*函数指针变量名)(参数列表);
	void (*funcp)(int num1, int num2);
//	该函数指针的类型是
返回值 (*)(参数列表);	
	void (*)(int, int);
//	函数指针类型重定义
typedef 返回值 (*重定义后的类型名)(参数列表);
	typedef void (*fp)(int, int);
	fp 就是 void (*)(int, int)这个函数指针类型 可以用来定义该类型的函数指针变量
	fp p;	//	p就是函数指针变量

代码实现

posted @   sleeeeeping  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
  1. 1 吹梦到西洲 恋恋故人难,黄诗扶,妖扬
  2. 2 敢归云间宿 三无Marblue
敢归云间宿 - 三无Marblue
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

敢归云间宿 - 三无Marblue

词:怀袖

曲:KBShinya

编曲:向往

策划:杨颜

监制:似雨若离RainJaded/杨颜

吉他:大牛

混音:三无Marblue

和声:雾敛

母带:张锦亮

映像:似雨若离RainJaded

美术:阿尼鸭Any-a/乙配/雨谷/今风/米可/Eluan

题字:长安

酒 泼去群山眉头

酒 泼去群山眉头

月 悬在人世沧流

空杯如行舟 浪荡醉梦里走

心 生自混沌尽头

心 生自混沌尽头

对 天地自斟自酬

诗随我 遍历春秋

行流水 走笔形生意动

见珠玉 淙淙落纸成诵

拾得浮名有几声 云深处 却空空

耳畔丝竹 清商如雾

谈笑间 却是心兵穷途

飞觞醉月无归宿 便是孤独

不如就化身为风

卷狂沙 侵天幕

吹醒那 泉下望乡 的战骨

昨日边关犹灯火

眼前血海翻覆

千万人跌落青史 隔世号呼

于是沸血重剑共赴

斩以雷霆之怒

肩背相抵破阵开路

万古同歌哭

纵他春风不度 悲欢蚀骨

此去宁作吾

挣过命途 才敢写荣枯

望 云际群龙回首

望 云际群龙回首

任 飘蓬争逐身后

叹冥顽之俦 好景尽付恩仇

收 江声随酒入喉

收 江声随酒入喉

来 提笔御风同游

不觉已 换了春秋

真亦假 泼墨腾烟沉陆

有还无 蝶影纷堕幻目

我与天地周旋久

写尽梦 便成梦

夜雨浇熄 往事残烛

生死间 谁尽兴谁辜负

管他醒来归何处 心生万物

也曾对电光火雨

抛酒樽 镇天枢

护住了 人间多少 朝与暮

烧尽了阴云冥府

烧尽了阴云冥府

且看星斗尽出

浩荡荡尘埃野马 忘怀命数

于是信步鸿蒙之轻

也领苍生之重

与诗与剑颠倒与共

沉眠斜阳中

纵他世事汹涌 万类争渡

此去宁作吾

醉得糊涂 才梦得清楚

潮水 带着叹息轻抚

潮水 带着叹息轻抚

像光阴 漫过大地上幽微草木

有情世 见众生明灭往复

天生自在 何必回顾

晦暗中双掌一拊

立此身 照前路

与某个 阔别的我 决胜负

渺渺兮身外无物

无喜无悲无怖

不过是大梦一场 各自沉浮

于是纵横万相穷通

也守心底灵通

合眼识得星沉地动

也岿然不动

敢令岁月乌有 逍遥长驻

敢归云间宿

遥祝远行人 有道不孤

点击右上角即可分享
微信分享提示