数据结构之栈

一、栈

1.1 栈的定义

  • 栈(Stack):只允许在一端进行插入或删除操作的线性表。首先栈是一种线性表,但是限定这种线性表只能在某一端进行插入和删除操作。
  • 栈顶(Top):线性表允许进行插入和删除的那一端。
  • 栈底(Bottom):固定的,不允许进行插入和删除的另一端。
  • 空栈:不含任何元素的空表。

1.2 栈的基本操作

  • InitStack(&S):初始化一个空栈 S。
  • StackEmpty(S):判断一个栈是否为空,若栈 S 为空返回 true,否则返回 false。
  • Push(&S,x):进栈,若栈 S 未满,将 x 加入使之成为新栈顶。
  • Pop(&S,&x):出栈,若栈 S 非空,弹出栈顶元素,并用 x 返回。
  • GetTop(S,&x):读栈顶元素,若栈顶元素为空,用 x 返回栈顶元素。
  • ClearStack(&S):销毁栈,并释放栈 S 占用的存储空间。

1.3 栈的顺序存储结构

  • 顺序栈的实现:栈的顺序存储称为顺序栈,是利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针(Top)指示当前栈顶的位置。
  • 顺序栈的基本运算:初始化、判栈空、进栈、出栈、读栈顶元素。
  • 共享栈:利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数据空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延申。

1.4 栈的链式存储结构

  • 采用链式存储的栈成为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。
  • 通常采用单链表实现,并规定所有操作都是在单链表的表头进行。
  • 采用链式存储,便于结点的插入与删除。

二、队列

2.1 队列的定义

  • 队列简称队,是一种操作受限的线性表,只允许在表的一端进行插入,而在表的另一端进行删除。向队列中插入元素称为入队或进队;删除元素称为出队或离队。
  • 操作特性为先进先出,又被称为先进先出的线性表。
  • 队头(Front):允许删除的一端,又称为队首。
  • 队尾(Rear):允许插入的一端。
  • 空队列:不含任何元素的空表。

2.2 队列的顺序存储结构

  • 队列的顺序存储:队列的顺序实现是指分配一块连续的存储单元存放队列中的元素,并附设两个指针 front 和 rear 分别指示队头元素和队尾元素的位置。
  • 初始条件(对空条件):Q.front == Q.rear == 0;
  • 进队操作:队不满时,先送值到队尾元素,再送队尾指针加 1。
  • 出队操作:队不空时,先取队头元素值,再将队头指针加 1。
  • 队空条件为:Q.rear == MaxSize ;

2.3 循环队列

  • 把存储队列元素的表从逻辑上看成一个环,当队首指针 Q.front = MaxSize-1后,再前进一个位置就自动到 0,可利用除法取余(%)来实现。
  • 初始时:Q.front = Q.rear = 0;
  • 队首指针进 1:Q.front = (Q.front+1)%MaxSize;
  • 队尾指针进 1:Q.rear = (Q.rear+1)%MaxSize;
  • 队列长度:(Q.rear+MaxSize-Q.front)%MaxSize;
  • 出队入队时:指针都按顺时针方向进 1;
  • 牺牲一个单元来区分队空和队满,入队少用一个队列单元,即队头指针在队尾指针的下一个位置作为队满的标志。
  • 队满条件为:(Q.rear+1)%MaxSize==Q.front。
  • 队空条件为:Q.front == Q.rear。
  • 队中元素的个数:(Q.rear-Q.front+MaxSize)%MaxSize
  • 类型中增设表示元素个数的数据成员
  • 队空:Q.size = 0;
  • 队满:Q.size = MaxSize;
  • 上述两种情况均有Q.front = Q.rear
  • 类型中增设 tag 数据成员,以区分是队空还是队满。
  • tag 等于零的情况下,若因删除导致Q.front == Q.rear 则为队空;
  • tag 等于 1 的情况下,若因插入导致Q.front == Q.rear 则为队满;
  • 循环队列的操作:初始化,判队空,入队,出队

2.4 队列的链式存储结构

  • 队列的链式表示称为链队列,是一个同时带有队头指针和队尾指针的单链表。
  • 头指针指向头节点,尾指针指向尾结点,即链表的最后一个结点。
  • 当 Q.front == NULL,且 Q.rear == NULL 时,链表队列为空。
  • 出队时,首先判断队是否为空,若不空,则取出队头元素,将其从链表中摘除,并让 Q.front 指向下一个结点(若该节点为最后一个节点,则置 Q.front 和 Q.rear 都为NULL)。
  • 入队时,建立一个新节点,将新节点插入到链表的尾部,并改让 Q.rear 指向这个新插入的结点(若原队列为空队,则令 Q.front 也指向该节点。
  • 用单链表表示的链式队列特别适合于数据元素变动比较大的情形,而且不存在队列满且产生溢出的问题。
  • 假如程序中要使用多个队列,于多个栈的情况一样,最好使用链式队列,这样就不会出现存储分配不合理和溢出的问题。
  • 链式队列的基本操作:初始化,判队空,入队,出队

2.5 双端队列

  • 双端队列是指允许两端都可以进行入队和出队操作大的队列,其元素的逻辑结构仍是线性,将队列的两端分别称为前端和后端,两边都可以入队和出队。
  • 在双端队列进队时:前端进的元素排列在队列中后端进的元素后面,后端进的元素排列在队列中前端元素进的元素的后面。
  • 在双端队列出队时:无论前端还是后端出队,先出的元素排在后出的元素前面。
  • 输出受限的双端队列:允许在一端进行插入和删除,但在另一端只允许插入的双端队列称为输出受限的双端队列。
  • 输入受限的双端队列:允许在一端进行插入和删除,但在另一端只允许删除的双端队列称为输入受限的双端队列。而如果限定双端队列从某个端点插入的元素只能从该端点删除,则该双端队列就蜕变为两个栈底相邻接的栈了。

三、栈和队列的应用

  • 栈在括号匹配中的应用
  • 栈在表达式求值中的应用
  • 栈在递归中的应用
  • 队列在层次遍历中的应用
  • 队列在计算机系统中的应用

四、特殊矩阵的压缩存储

  • 矩阵在计算机图形学、工程计算中占有举足轻重的地位,在数据结构中考虑的是如何用最小的内存空间来存储同样的一组数据。

4.1 数组

  • 数组和线性表的关系:数组是线性表的推广。一维数组可以看作是一个线性表,二维数组可以看作元素是线性表的线性表,以此类推。
  • 数组一旦被定义,它的维数和维界就不再改变,因此,除了结构的初始化和销毁之外,数组就只会有存取元素和修改元素的操作。

4.2 数组的存储结构

  • 一个数组的所有元素在内存中占用一端连续的存储空间。
  • 对于多维数组,有两种映射方法 :按行优先和按列优先。
  • 按行优先:先行后列,先存储行号较小的元素,行号相等先存储列号较小的元素。
  • 按列优先:先列后行。

4.3 矩阵的压缩存储

  • 压缩存储:指为多个值相同的元素只分配一个存储空间,对零元素不分配存储空间,其目的是为了节省存储空间。
  • 特殊存储:指具有许多相同矩阵元素或零元素,并且这些相同矩阵元素或零元素的分布有一定规律性的矩阵。常见的特殊矩阵有对称矩阵、上(下)三角矩阵、对角矩阵等。
  • 特殊矩阵的压缩存储方法:找出特殊矩阵中值相同的矩阵元素的分布规律,把那些呈现规律性分布的值相同的多个矩阵元素压缩存储到一个存储空间中。

4.4 稀疏矩阵

  • 矩阵元素个数 s 相对于矩阵中非零元素个数 t 来说非常多,即 s >> t 为的矩阵称为稀疏矩阵。
  • 将非零元素及其相应的行和列构成一个三元组(行标,列标,值),然后按照某种规律存储这些三元组。
  • 稀疏矩阵压缩存储后便失去了随机存取的特性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值