首页 > 其他分享 >数据结构-线性表、链表

数据结构-线性表、链表

时间:2024-07-20 11:39:56浏览次数:15  
标签:存储 线性表 元素 链表 数据结构 节点 指针

一、线性表介绍

1、线性结构

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

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

线性表是一个有n个数据元素的有限序列,同一个线性表中的元素必定有相同特性,元素之间存在序偶关系

线性表中的元素个数\(n(n \leq 0)\)定义为该表的长度,当\(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、不带头节点的单向链表

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

​ 注意:当需要对单链表的头指针发生修改时,例如头添加、头删除、插入等操作,参数需要传递头指针的地址(二级指针),处理相对麻烦

​ 注意:当进行删除时,需要获取到待删除节点的前趋节点,但是如果删除的位置刚好是第一个节点,它没有前趋节点,所以需要额外判断处理

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就是函数指针变量

标签:存储,线性表,元素,链表,数据结构,节点,指针
From: https://www.cnblogs.com/sleeeeeping/p/18303764

相关文章

  • 链表带环问题简单讲解
     #带环链表解题思路对于这道题我们可以定义两个指针,一个快指针,一个慢指针。快指针一次走两步,慢指针一次走一步。这样快指针就会比慢指针先进入环内。慢指针进入环后,这个问题就会演变成一个追击问题,即:快指针能否追上慢指针并与之重合。假设,慢指针进入环后与快指针的距......
  • PYTHON学习笔记(六、python数据结构--字典)
    (3)dict字典字典数据类型的含义是:根据一个信息查找另一个信息的方式构成了“键值对”,它表示索引用的键和对应的值构成对应的关系。1、字典的创建方式1)使用{ }直接创建字典使用{ }创建字典的语法结构如下:d={key1:value1,key2:value2......}例如:#使用{}创建字典d=......
  • 数据结构:栈
    数据结构:栈满足栈的特性,只有先进后出的特性,不能遍历,也就不能遍历打印,也不能随机访问。栈栈:栈是在处理数据时是先进后出、就是先进栈的数据最后一个出栈、最后一个进栈的数据第一个出栈、栈就类似于给一把手枪弹夹压子弹,给弹夹压子弹的顺序就如同数据进栈的顺序,第一颗子......
  • 数据结构(队列)
    文章目录一、概念与结构二、队列的实现QueueNode.hQueue.c初始化判断队列为空队尾,入队列队头,出队列取队头数据取队尾数据取队列有效元素个数销毁队列test.c一、概念与结构......
  • 数据结构_排序
    目录一、排序二、插入排序2.1直接插入排序2.2希尔排序三、选择排序3.1直接选择排序3.2堆排序四、交换排序4.1冒泡排序4.2快速排序五、归并排序六、排序算法分析总结一、排序排序:就是使一串记录序列,按照其中某个或某些关键字的大小,进行递增或递减的排列......
  • 算法第十一天:leetcode707.设计链表
    一、设计链表的题目描述与链接  707.设计链表的链接如下表所示,您可直接复制下面网址进入力扣学习,在观看下面的内容之前一定要先做一遍哦,这样才能印象深刻!https://leetcode.cn/problems/design-linked-list/https://leetcode.cn/problems/design-linked-list/题目描述:你......
  • 【数据结构】学习day 1.1线性表中的顺序表
    1 "&"区别(c++)#include<stdio.h>voidtest(intx){   x=2024;   printf("intestx=%d\n",x);}intmain(){   intx=1;   printf("beforetestx=%d\n",x);   test(x);   printf("aftertestx=%d\n"......
  • 数据结构——哈希
    前言顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(logN),搜索的效率取决于搜索过程中元素的比价次数。理想的搜索方法:可以不经过任何比较,一次直接从表中得......
  • 数据结构—双向链表
    文章目录1.双向链表的概念和结构1.1双向链表的概念1.2双向链表与单链表的对比1.3双向链表的结构2.双向链表的接口实现2.1申请一个新结点2.2初始化2.3打印2.4尾插2.5头插2.6判断链表是否为空2.7尾删2.8头删2.9查找2.10在指定位置之后插入数据2.11在指定位......
  • 线性表——链表(c语言)
    链表概念篇示意图1.单向链表2.双向链表3.循环链表4.链表的元素插入5.链表的元素删除代码篇1.链表的定义2.链表的创建3.链表的销毁4.链表的元素插入5.链表的元素删除6.链表的元素查找7.链表下标对应的结点8.链表元素的修改9.链表的打印10.完整代码代码运行效果概......