数据结构之顺序存储与链式存储
数据结构之顺序存储与链式存储
- 定义
- 特点
- 前驱和后继
- 存储结构
- 顺序存储结构
- 定义
- 特点
- 优缺点
- 基本操作
- 链式存储结构
- 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、单链表
节点
一个完整的链表需要由以下几部分构成:
**头指针:**一个普通的指针,它的特点是永远指向链表第一个节点的位置。很明显,头指针用于指明链表的位置,便于后期找到链表并使用表中的数据;
节点:链表中的节点又细分为头节点、首元节点和其他节点:
- **头节点:**其实就是一个不存任何数据的空节点,通常作为链表的第一个节点。对于链表来说,头节点不是必须的,它的作用只是为了方便解决某些实际问题;
- **首元节点:**由于头节点(也就是空节点)的缘故,链表中称第一个存有数据的节点为首元节点。首元节点只是对链表中第一个存有数据节点的一个称谓,没有实际意义;
- **其他节点:**链表中其他的节点;
链表中有头节点时,头指针指向头节点;反之,若链表中没有头节点,则头指针指向首元节点。
基本操作
结构体定义
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. 线性结构 特点:除第一个元素只有一个"后继"和最后一个元素只有一个"前驱",其它每个元素只有一个"前驱"元素和一个"后继&q ...
- Python 数据结构 之 串 的链式存储结构
本文所采用的数据结构模板为 <数据结构教程>C语言版,李春葆.尹为民等著. 改篇所涉及到的是 串 的链式存储结构. 用Python仿照C语言来实现. 文章转载请注明: Python 数据 ...
- 栈的存储——顺序存储与链式存储
文章目录 栈的存储 顺序存储 定义 代码实现 栈顶指针与栈中元素在内存中的存储 初始化栈及其代码 判断栈空及其代码 进栈操作及其代码 出栈操作及其代码 读取栈顶元素操作及其代码 顺序栈的缺点 共享栈 ...
- 【数据结构笔记05】堆栈及其顺序存储、链式存储
本次笔记内容: 2.2.1 什么是堆栈 2.2.2 堆栈的顺序存储实现 2.2.3 堆栈的链式存储实现 2.2.4 堆栈的应用:表达式求值 文章目录 引:计算机如何进行表达式求值? 堆栈的抽象数据类型 ...
- 数据结构与算法(6-2)二叉树的存储结构(顺序存储、链式存储)
目录 一.二叉树的顺序存储 存储方式 总代码 二.二叉树的链式存储(二叉链表) 1.存储结构 2.创建二叉树 总代码 一.二叉树的顺序存储 存储方式 //树的顺序存储 typedef struct { ...
- 【数据结构笔记06】队列及其顺序存储、链式存储
本次笔记内容: 2.3.1 队列及顺序存储实现 2.3.2 队列的链式存储实现 文章目录 什么是队列 队列的顺序存储实现 循环队列 队列的链式存储实现 什么是队列 队列(Queue):具有一定操作约束 ...
- 数据结构与算法2:线性表的顺序存储与链式存储
文章目录 线性表 定义 线性表的抽象数据类型(Abstract Data Type) 线性表的顺序存储结构 线性表的链式存储结构 单链表(single linked list) 静态链表 (stati ...
- Python数据结构与算法基础|第二期:代码实现——栈的顺序存储与链式存储
顺序存储的栈 由于Python内置的列表是顺序存储的,所以我们直接使用列表作为顺序存储的栈的底层.具体代码如下: class Stack(object):'实现顺序栈.'def __init__(se ...
- 数据结构之线性表-链式存储之单链表(一)
本人文笔较差,语文从来不及格,基础不好,写此类文章仅供自己学习,理解队列及其他知识,高手大神请略过.参考书籍 <数据结构与算法分析-Java语言描述> 1.1 单链表简介 线性表的最大的缺 ...
最新文章
- 【路径规划】Dijkstra算法——超详细原理图解
- Github GAN 非平稳纹理合成
- 基于 Module 的 Laravel API 架构
- AR头显要上天!欧洲太空总署或用HoloLens维修太空站
- 进入全真互联网——音视频通信的技术变革
- oracle的等保,3.Oracle 检查(部分)
- 将您重定向的次数过多什么意思_忙忙碌碌将爱麻木是什么歌-所以会忙忙碌碌将爱麻木歌曲意思、出处、含义介绍...
- GitHub 的 12 个实用技巧,你 get 了几个?
- 老罗Android开发视频教程_基于JavaSE开发(适合Android初学者菜鸟级别的人)
- Delphi源码网站
- dede采集简单好用的织梦采集
- java web 教学视频_超全面的JavaWeb视频教程
- 什么是分布式定时任务框架?
- 安卓手机怎么投屏台式计算机,怎么将手机投屏到台式电脑上
- 牛客寒假集训营 牛牛战队的比赛地
- 数据防泄密·工控安全保障方案
- 水星路由器wan口ip显示0_路由器wan口状态全是0 路由器wan口状态ip为0-192路由网
- modelsim和vivado仿真不一致——噩梦debug
- 练习:三子棋(python 列表list“全局变量”特性、插值字符串格式化、set 元素不重复特性)
- SpringBoot是什么,可以做什么?