9.线性表及其顺序存储结构
- 线性表:由一组数据元素构成,数据元素的位置只取决于自己的序号,元素之间的相对位置是线性的。
- 线性表的顺序存储指的是将线性表的数据元素按其逻辑次序依次存入一组地址连续的存储单元,用这种方式存储的线性表称为顺序表
- 非空线性表的结构特征:
- 有且只有一个根节点,
- 有且只有一个终端节点
- 除根节点与终端节点外,其他所有结点有且只有一个前件,也有且只有一个后件
- 结点个数n称为线性表的长度,当n = 0 时,称为空表
- 线性表的顺序存储结构具有以下两个基本特点
- 线性表中所有元素所占的存储空间是连续的
- 线性表中各数据元素在存储空间中是按逻辑顺序依次存放的
- 顺序表(数组)与链表(线性表的链式存储结构)比较
- 顺序表:内存上是连续的存储空间
- 链表:内存地址可以是不连续的,每个链表的结点包括原来的内存和下一结点的信息
- 顺序表优点:
- 占用内存空间少
- 数组内的数据可以随机访问
- 数据查找效率较高
- 链表优点:
- 方便数据的删除、插入
- 长度可变,扩展性好
- 内存 利用率高
- 顺序表插入或删除元素的时间内复杂度O(n),链表插入或删除元素的时间复杂度O(1)
- 顺序表利用下标访问,时间复杂度为O(1),链表访问元素时间复杂度O(n)
- 假设线性表中的第一个数据元素的存储地址为LOC(a1),每一个数据元素占d个字节,则线性表中第i个元素ai在计算机存储空间的地址:LOC(ai) = LOC(a1)+(i-1)d
- 顺序表的插入操作
- 首先处理以下三种异常情况
- 当存储空间已满(即n = m)时为“上溢”错误,不能进行插入,算法结束
- 当 i > n 时,认为在最后一个元素之后(即第 n + 1 个元素前)插入
- 当 i < n 时,认为在第一个元素之前插入
- 从最后一个元素开始,直到第一个元素,其中每一个元素均往后移动一位
- 最后将新元素插入到第i位,并且将线性表长度加1
- 顺序表的插入操作算法分析:
- 最好的情况: i = n + 1 (插入尾元素),移动次数为0
- 最坏的情况: i = 1(插入第一个元素),移动次数为n
- 平均情况:在位置i插入新元素x,需要将ai~an的元素均后移一次,移动次数为n-i+1.移动元素的平均次数n/2
- 插入算法的主要时间花费在元素移动上,所以算法平均时间复杂度为O(n)
- 顺序表的删除操作
- 首先处理以下三种异常情况
- 当存储空间为空(n = 0)时为“下溢”操作,不能进行删除,算法结束
- 当i < 1 或 i > n 时,认为不能删除,算法结束
- 从第 i + 1 个元素开始,直到最后一个元素,其中每一个元素均依次往前移动一个位置
- 最后将线性表的长度减去1
- 顺序表的操作算法分析
- 最好的情况:当 i = n(删除尾元素),移动次数为0
- 最坏的情况:当 i = 1 (删除第一个元素),移动次数为n-1
- 平均情况:在位置 i 删除元素 x ,需要将 ai+1~an的元素均前移一位,移动次数n -i,移动元素的平均次数 (n-1)/2
- 删除算法的主要时间花费在元素移动上,所以算法平均时间复杂度为O(n)
10.栈
- 栈是一种特殊的线性表,只允许在表的一端进行插入和删除的线性表,通常插入,删除的一端为栈顶,另一端为栈底,当表中没有元素时为空栈
- 栈是一种先进后出或后进先出的线性表,栈具有记忆功能
- 栈顶指针top动态反映了栈中元素的变化情况
- 栈的存储结构:
- 顺序栈:用一组地址连续的存储单元
与一般的线性表一样,程序设计语言中,用一维数组作为栈的顺序存储空间,其中为栈的最大容量,通常栈底指针向栈空间的低地址一端(即数组的起始地址这一端)
在栈的顺序存储空间通常为栈底元素(在栈非空的情况下),S(top)为栈顶元素,top=0表示栈空;top = m 表示栈满 - 链栈(链式存储结构):用线性链表来存储;
- 顺序栈的基本运算
- 入栈运算是指在栈顶位置插入一个新元素,操作过程如下:
- 首先判断栈顶指针是否已经指向存储空间的最后一个位置,如果是,则说明栈空间已满,不可能现进行入栈操作,算法结束
- 然后将栈顶指针进一
- 最后将新元素x插入栈顶指针指向的位置
- 退栈运算,删除元素(取出栈顶元素并赋予一个指定的变量)。操作过程如下
- 首先判断栈顶指针是否为0,如果是,则说明栈空,不可能进行退栈操作,算法结束
- 然后将栈顶元素赋予一个指定的变量
- 最后将栈顶指针退一
- 读栈顶元素,将栈顶元素赋给一个指定的变量,此时指针无变化,该运算不能删除栈顶元素,操作过程如下
- 首先判断栈顶指针是否为0,如果是,则说明栈空,读不到栈顶元素,算法结束
- 然后将栈顶元素赋给指定的变量y
- 在栈中,栈底保持不变,有元素入栈,栈顶指针增加,有元素出栈,栈顶指针减小
11.队列
- 队列是一种特殊的线性表,只允许在表的一端插入,在另一端删除,允许插入的一段是队尾,允许删除的一端为队头,当表中没有元素是空列队,列队是一种先进先出或者后进后出的线性表
- 队列的存储结构:
- 队列的顺序存储结构:队列的顺序实现是指分配一块连续的存储单元存放队列中的元素,并附设两个指针,队头指针front指向队头元素,队尾指针rear指向队尾元素
- 队列的链式存储结构:其实就是线性表的单链表,只不过它只能尾进头出,我们把它称为链队列
- 队列的顺序结构一般采用循环的形式。
- 队列的基本运算,假设循环对联的初始状态为空 S = 0 ,且 rear = front = m
- 入队运算时指在循环队列的队尾加入一个新元素,操作过程如下:
- 首先判断循环队列是否满,当循环队列非空且队尾指针等于排头指针时,说明循环队列已满,不能进入队运算,
- 然后将队尾指针进一
- 最后将新元素x插入队尾指针指向的位置,并且置循环队列非空标志
- 退队运算是指在循环队列的排头位置退出一个元素并赋值给指定的变量。操作过程如下:
- 首先判断循环队列是否为空,当循环队列为空(s=0)时,不能进行退队运算,算法结束
- 然后将排头指针进一,并当front = m + 1 时置 front = 1
- 再将排头指针指向的元素赋给指定的变量
- 最后判断退队之后循环队列是否为空,当 front = rear 时置循环队列为空标志
- 在循环队列中,队头指针和队尾指针的动态变化决定队列的长度
- 对于栈用栈顶指针表示栈顶,而栈的插入和删除操作均在栈顶进行,对于队列用队头和队尾指针分别表示允许删除和插入的一端,因此对于顺序存储和链式存储的栈和队列,进行插入和删除运算的时间复杂度均为O(1)。