数据结构之顺序存储与链式存储

  • 定义
  • 特点
  • 前驱和后继
  • 存储结构
    • 顺序存储结构
      • 定义
      • 特点
      • 优缺点
      • 基本操作
    • 链式存储结构
    • 1、单链表
      • 节点
      • 基本操作
    • 2、静态链表
    • 3、双向链表
    • 4、循环链表
  • 顺序存储和链式存储比较

定义

线性表,全名为线性存储结构。

线性表是n个数据特性相同的元素的组成有限序列,是最基本且常用的一种线性结构(线性表,栈,队列,串和数组都是线性结构),同时也是其他数据结构的基础。具有“一对一”逻辑关系的数据,最佳的存储方式是使用线性表。

特点

  • 是一个有限的序列
  • 可以是有序的也可以是无序的。
  • 线性表的开始元素没有前驱元素只有后继元素,线性表的结束元素没有后继元素只有前驱元素,除了开头元素和结尾元素以外,每个元素都有且只有一个前驱元素和后继元素。

前驱和后继

数据结构中,一组数据中的每个个体被称为“数据元素”(简称“元素”)。

  • 某一元素的左侧相邻元素称为“直接前驱”,位于此元素左侧的所有元素都统称为“前驱元素”;
  • 某一元素的右侧相邻元素称为“直接后继”,位于此元素右侧的所有元素都统称为“后继元素”;

以下图数据中的元素 3 来说,它的直接前驱是 2 ,此元素的前驱元素有 2 个,分别是 1 和 2;同理,此元素的直接后继是 4 ,后继元素也有 2 个,分别是 4 和 5。

存储结构

线性表存储结构分为顺序存储结构链式存储结构,前者称为顺序表,后者称为链表。

顺序存储结构

定义

顺序表就是把线性表中的所有元素按照某种逻辑顺序,依次存储到从指定位置开始的一块连续的存储空间。

特点

逻辑上相邻的数据元素,物理次序也是相邻的。

只要确定好了存储线性表的起始位置,线性表中任一数据元素都可以随机存取,所以线性表的顺序存储结构是一种随机存取的储存结构,因为高级语言中的数组类型也是有随机存取的特性,所以通常我们都使用数组来描述数据结构中的顺序储存结构,用动态分配的一维数组表示线性表。

**数组长度和线性表的长度区别:**数组长度是存放线性表的存储空间的长度,存储分配后这个量一般是不变的,线性表的长度是线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的。

优缺点

优点 缺点
无需为表示表中元素之间的逻辑关系而增加额外的存储空间 插入和删除操作需要移动大量元素
可快速的存取表中的任一位置元素 当线性表长度变化比较大时,难以确定存储空间的容量
容易造成存储空间碎片

基本操作

结构体定义

顺序表可以分为静态分配和动态分配两种:

  • 静态分配
#define MaxSize 50  / /顺序表的最大长度
typedef struct{     // typedef类型重命名ElemType data[MaxSize]; // 顺序表的元素,ElemType是未明确的数据类型,使用时可以用typedef定义具体类型int length;             // 长度
}SqList;

静态分配方法需要预先分配一段固定大小的连续空间,但在运算过程中,进行插入,合并等操作时,容易超过预分配的空间长度,出现溢出问题。

  • 动态分配
#define InitSize 50  // 顺序表的初始长度
typedef struct{     // typedef类型重命名ElemType *data; // 指向动态分配数组的指针,基地址,*取内容int MaxSize;    // 数组的最大容量int length;   // 数组的当前个数
}SeqList;
// 定义SqList类型的变量
SqList L;
L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);

初始化

struct SqList{int data[MaxSize]; // 存放顺序表的元素int length; // 存放顺序表的长度int last;
};void Init(SqList *L){L->data[0] = int(malloc(MaxSize * sizeof(int)));int n, i = 0;cin >> n;L->length = n;while (i < n){cin >>(L->data[i++]);}L->last = i - 1;
}

插入

bool InsertList(SqList &L, int i, int e)
{// 在顺序表中第i个位置(位序,不是下标)插入数值eint j;if (i<1 || i>L.length+1) // 是否越界return false;if (L.length == MaxSize)// 内存已满return false;L.length++;            // 长度++for (j = L.length; j >= i; j--) // 将第i个起的数据后移L.data[j] = L.data[j - 1];L.data[j] = e;return true;
}

删除

bool DeleteList(SqList&L, int i)
{// 删除顺序表中第i个元素int j;if (i<1 || i>L.length)return false;   // 判断越界for (j = i; j < L.length; j++)L.data[j - 1] = L.data[j];L.length--;return true;
}

查找

bool LocateElem(SqList L, int e)
{int i;for(i = 0; i < L.length; i++){if(L.data[i] == e){return i+1;}}return 0;
}

链式存储结构

又称为链表,用于存储逻辑关系为 “一对一” 的数据。

用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的),包括数据域和指针域,数据域存数据,指针域指示其后继的信息。

1、单链表

节点

一个完整的链表需要由以下几部分构成:

  1. **头指针:**一个普通的指针,它的特点是永远指向链表第一个节点的位置。很明显,头指针用于指明链表的位置,便于后期找到链表并使用表中的数据;

  2. 节点:链表中的节点又细分为头节点、首元节点和其他节点:

    • **头节点:**其实就是一个不存任何数据的空节点,通常作为链表的第一个节点。对于链表来说,头节点不是必须的,它的作用只是为了方便解决某些实际问题;
    • **首元节点:**由于头节点(也就是空节点)的缘故,链表中称第一个存有数据的节点为首元节点。首元节点只是对链表中第一个存有数据节点的一个称谓,没有实际意义;
    • **其他节点:**链表中其他的节点;

链表中有头节点时,头指针指向头节点;反之,若链表中没有头节点,则头指针指向首元节点。

基本操作

结构体定义

typedef struct Lnode{    ElemType data; struct Lnode *next;
}LNode,*LinkList

初始化

单链表的初始化是指构建一个空表。先创建一个空结点,不存放数据,然后令其指针域为空;

bool InitList_L(LinkList &L){L = new Lnode; if(!L) return false;L -> next = NULL;return true;
}

创建

创建单链表分为头插法和尾插法两种。

  • 头插法:是指每次将新结点插入到头结点之后,其创建的单链表和数据输入的顺序正好相反,因此也称为逆序建表。
void CreateList_H(LinkList &L){int n;LinkList s;L = new LNode;L -> next = NULL;cin>>n;while(n--){s = new LNode;cin>>s->data;s->next = L->next;L->next = s;}
}
  • 尾插法:是指每次把新结点链接到链表的尾部,其创建的单链表和数据输入顺序一致,因此也称为正序建表。
void CreatList_R(LinkList &L){   int n;LinkList s, r;L = new Lnode;L -> next = NULL;r = L;cin>>n;while(n--){s = new LNode; cin >> s->data;s -> next = NULL; r -> next = s;r = s; }
}

按序取值
从单链表的第一个结点出发,顺指针逐个往下搜索,知道找到第i个结点为止,否则返回最后一个结点的指针NULL。

LinkList GetElem(LinkList L, int i){int j = 1; LinkList p = L -> next;if(i == 0) return L;if(i < 1) return NULL;while(p && j<i){p = p->next;j++;}return p;
}

插入结点

p = GetElem(L, i-1);
s -> next = p -> next;
p -> next = s;

删除结点

p = GetElem(L, i-1);
q = p -> next;
p -> next = q -> next;

2、静态链表

静态链表,兼顾了顺序表和链表的优点于一身。

使用静态链表存储数据,数据全部存储在数组中(和顺序表一样),但存储位置是随机的,数据之间"一对一"的逻辑关系通过一个整形变量(称为"游标",和指针功能类似)维持(和链表类似)。

3、双向链表

在单链表的基础上,再在每个结点中设置一个指向其前驱结点的指针域,这样一个结点既可以指向它的前面又可以指向它的下一个,我们把这种链表称为双向链表。

4、循环链表

将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。

顺序存储和链式存储比较

  • 顺序表只需知道第一个元素的位置,就可以通过起始位置的偏移去获取顺序表中的任何元素(随机访问),而链表的存储结构是一个元素中包含下一个数据元素的位置信息,下一个包含下下一个,也就是每个数据元素之间都是单线联系的,你要想知道最后一个元素在哪里,你必须从头走到尾才可以,所以链表是不支持随机访问的。
  • 顺序表中的数据元素是存放在一段地址连续的空间中,且这个存储空间是提前分配的,一旦分配好了,在对其进行操作的过程中是不会更改的。而链表支持存储空间动态分配。
  • 顺序表在插入删除一个元素的时候需要移动大量元素。而链表在插入和删除一个元素时,不需要移动大量元素,只需要更改插入位置的指针指向就可以。

本篇完

数据结构之顺序存储与链式存储相关推荐

  1. 线性结构(顺序存储和链式存储)和非线性结构的特点及区别

    1. 线性结构 特点:除第一个元素只有一个"后继"和最后一个元素只有一个"前驱",其它每个元素只有一个"前驱"元素和一个"后继&q ...

  2. Python 数据结构 之 串 的链式存储结构

    本文所采用的数据结构模板为 <数据结构教程>C语言版,李春葆.尹为民等著. 改篇所涉及到的是 串 的链式存储结构. 用Python仿照C语言来实现. 文章转载请注明:  Python 数据 ...

  3. 栈的存储——顺序存储与链式存储

    文章目录 栈的存储 顺序存储 定义 代码实现 栈顶指针与栈中元素在内存中的存储 初始化栈及其代码 判断栈空及其代码 进栈操作及其代码 出栈操作及其代码 读取栈顶元素操作及其代码 顺序栈的缺点 共享栈 ...

  4. 【数据结构笔记05】堆栈及其顺序存储、链式存储

    本次笔记内容: 2.2.1 什么是堆栈 2.2.2 堆栈的顺序存储实现 2.2.3 堆栈的链式存储实现 2.2.4 堆栈的应用:表达式求值 文章目录 引:计算机如何进行表达式求值? 堆栈的抽象数据类型 ...

  5. 数据结构与算法(6-2)二叉树的存储结构(顺序存储、链式存储)

    目录 一.二叉树的顺序存储 存储方式 总代码 二.二叉树的链式存储(二叉链表) 1.存储结构 2.创建二叉树 总代码 一.二叉树的顺序存储 存储方式 //树的顺序存储 typedef struct { ...

  6. 【数据结构笔记06】队列及其顺序存储、链式存储

    本次笔记内容: 2.3.1 队列及顺序存储实现 2.3.2 队列的链式存储实现 文章目录 什么是队列 队列的顺序存储实现 循环队列 队列的链式存储实现 什么是队列 队列(Queue):具有一定操作约束 ...

  7. 数据结构与算法2:线性表的顺序存储与链式存储

    文章目录 线性表 定义 线性表的抽象数据类型(Abstract Data Type) 线性表的顺序存储结构 线性表的链式存储结构 单链表(single linked list) 静态链表 (stati ...

  8. Python数据结构与算法基础|第二期:代码实现——栈的顺序存储与链式存储

    顺序存储的栈 由于Python内置的列表是顺序存储的,所以我们直接使用列表作为顺序存储的栈的底层.具体代码如下: class Stack(object):'实现顺序栈.'def __init__(se ...

  9. 数据结构之线性表-链式存储之单链表(一)

    本人文笔较差,语文从来不及格,基础不好,写此类文章仅供自己学习,理解队列及其他知识,高手大神请略过.参考书籍 <数据结构与算法分析-Java语言描述> 1.1 单链表简介 线性表的最大的缺 ...

最新文章

  1. 【路径规划】Dijkstra算法——超详细原理图解
  2. Github GAN 非平稳纹理合成
  3. 基于 Module 的 Laravel API 架构
  4. AR头显要上天!欧洲太空总署或用HoloLens维修太空站
  5. 进入全真互联网——音视频通信的技术变革
  6. oracle的等保,3.Oracle 检查(部分)
  7. 将您重定向的次数过多什么意思_忙忙碌碌将爱麻木是什么歌-所以会忙忙碌碌将爱麻木歌曲意思、出处、含义介绍...
  8. GitHub 的 12 个实用技巧,你 get 了几个?
  9. 老罗Android开发视频教程_基于JavaSE开发(适合Android初学者菜鸟级别的人)
  10. Delphi源码网站
  11. dede采集简单好用的织梦采集
  12. java web 教学视频_超全面的JavaWeb视频教程
  13. 什么是分布式定时任务框架?
  14. 安卓手机怎么投屏台式计算机,怎么将手机投屏到台式电脑上
  15. 牛客寒假集训营 牛牛战队的比赛地
  16. 数据防泄密·工控安全保障方案
  17. 水星路由器wan口ip显示0_路由器wan口状态全是0 路由器wan口状态ip为0-192路由网
  18. modelsim和vivado仿真不一致——噩梦debug
  19. 练习:三子棋(python 列表list“全局变量”特性、插值字符串格式化、set 元素不重复特性)
  20. SpringBoot是什么,可以做什么?

热门文章

  1. json_encode 中文不转义 tp5
  2. [机器学习]西瓜书南瓜书学习(更新中)
  3. 阿里云OSS文件批量打包下载
  4. 切片、切块、钻取和旋转
  5. 教你如何修改鼠标右键菜单背景图
  6. linux内核注册s pi驱动,Linux设备驱动Hello World程序介绍
  7. 30道数据挖掘笔试题,这都不懂就早点跑路吧
  8. stm32 神舟3号 开发板 usb DFU 实现
  9. 塔望食品品牌策划:预制菜主要竞争品牌分析及研究
  10. ansible启动heartbeat报错