文章目录
二、栈、队列和数组
这篇总结的主要是栈和队列的知识点,可以收藏下来,哪些地方概念不是特别清楚的时候翻出来看看。如果想看本章涉及到的代码部分,见文章下方超链接。
另外有些地方序号可能排版比较乱,之前在Typora上写的,导入过来之后貌似排序受到了影响,希望不影响阅读。
(一)栈和队列的基本概念
-
栈
-
栈的基本概念
- 一种只能在一端进行插入和删除的线性表。允许进行插入和删除的操作的称为栈顶(Top),表的另一端称为栈底,栈底固定不变。栈的插入和删除操作称为入栈和出栈。
- 栈顶有一个称为栈顶指针的位置指示器(就是一个变量,对于顺序栈,就是记录栈顶元素所在数组位置的标号的一个整型变量,对于链式栈,就是记录栈顶元素所在结点的指针,它是动态变化的)。
-
栈的特点
- 栈是一种在操作上稍加限制的线性表,本质还是线性表。
- 栈的主要特点就是先进后出FILO (Front In Last Out)。
-
栈的数学性质
- 当n个元素以某种顺序入栈,并且可以在任意时刻出栈(满足先进后出的前提),所获得的元素排列的数目N满足函数Catalan(),即
- 当n个元素以某种顺序入栈,并且可以在任意时刻出栈(满足先进后出的前提),所获得的元素排列的数目N满足函数Catalan(),即
-
栈的存储结构
- 顺序存储结构——顺序栈
- 链式存储结构——链式栈
-
形象的记忆方法就是:想象着一车队开进了死胡同。
-
-
队列
- 队列的基本概念
- 其限制为:仅在表的一端进行插入,另一端进行删除。可进行插入的称为队尾(Rear),可进行删除的称为队头(Front)。向队列中进行插入和删除元素称为入队和出队。
- 队列的特点
- 是一种先进先出FIFO(–First In First Out)的数据结构
- 队是一种在操作上稍加限制的线性表,本质还是线性表。
- 队列的存储结构
- 顺序存储结构——顺序队
- 链式存储结构——链式队
- 形象的记忆方法就是:想象着一车队开进了一个畅通的隧道。
- 队列的基本概念
(二)栈和队列的顺序存储结构
-
栈的顺序存储结构
-
栈的顺序存储又称为顺序栈,它是利用一组地址连续的存储单元一次性存放自栈底到栈顶的数据元素,同时设指针指示栈顶元素在顺序栈的位置。
-
顺序栈(st)的4个要素,包括两个状态和两个操作(下面为一般操作)
-
栈空状态
st.top = -1; //这里表示栈顶元素的数组下标,-1为不存在,代表栈内无结点
-
栈满状态
st.top = MAXSIZE - 1; //MAXSIZE是设置的栈内最大存储元素个数
-
进栈操作
st.Data[++st.top] = dat; //由于st.top初值为-1,这里需要先进行加1
-
出栈操作
dat = st.Data[st.top--]; //对应于进栈操作,这里st.top先取值再减1
-
-
-
队列
-
与栈一样,队列的顺序存储指的是利用一组地址连续的存储单元存放队列中的元素,并设置两个指针分别指示队头元素和队尾元素的存储位置的变量,分别称为队头指针front和队尾指针rear。
-
元素进队的时候,rear指针向后移动;元素出队的时候,front指针向后移动,这样到最后,就会出现假溢出。因此就产生了循环队列 。
-
循环队列
-
把数组弄成一个环,让front,rear指针沿着环走,这样就不永远不会出现两指针到数组的尽头不会往下走的情况了
-
循环队列(qu)的4个要素
-
队空状态
qu.rear = qu.front; //队首等于队尾
-
队满状态
(qu.rear+1) % MAXSIZE == qu.front; //队尾元素加1,取余最大元素个数若等于队头,则满
-
进队操作
qu.rear = (qu.rear+1) % MAXSIZE; //先将队尾下标向后移动一个位置 qu.Data[qu.rear] = dat; //进队
-
出队操作
qu.front = (qu.front+1) % MAXSIZE; //先将队头的下标向后移动一个位置 dat = qu.Data[qu.front]; //出队
-
-
-
(三)栈和队列的链式存储结构
-
栈的链式存储结构
-
栈的链式存储结构称为链栈。
-
栈只能在栈顶进行插入和删除,所以栈顶指针是必须的
-
链栈(lst)的4个要素:两个状态,两个操作
-
栈空状态
lst->next == NULL; //下个位置无结点
-
栈满状态:一般内存足够大,不存在栈满状态,
-
进栈操作(指针p所指进栈结点)
p->next = lst->next; //先将栈顶指针指向的结点赋值给p结点,使在其后 lst->next = p; //再将p结点的地址赋给栈顶结点,使p为栈顶指针所指
-
出栈操作(p所指出栈结点,x指结点内的数据信息)
p = lst->next; //将要出栈的结点赋值给p x = p->data; //获取结点中的数据 lst->next = p->next; //将栈顶指针向后指
-
-
-
队列的链式存储结构
-
队列的链式存储结构称为链队列。
-
链队(lqu)的4个要素:
-
队空状态:
lqu->front == NULL || lqu->rear == NULL //刚开始,两者都为空
-
队满状态:一般内存足够大,不存在栈满状态,
-
进队操作(指针p为进队结点)
lqu->rear->next = p; //先将p结点加到队尾指向的结点的后面 lqu->rear = p; //再将p结点所在地址赋值给队尾结点
-
出队操作(p为出队结点)
p = lqu.front; //先将要出队的元素地址赋值给p x = p.data; //取出p结点的数据 lqu.front = p.next; //再将p结点后的结点的地址赋值给队头元素 free(p); //释放内存
-
-
队头指针指向链队列的头结点,队尾指针指向终端节点。
-
(四)栈和队列的应用
- 栈
- 四则运算表达式求值
- 括号的匹配
- 队列
- 队列在计算机系统的应用
(五)特殊矩阵的压缩存储
- 压缩存储
- 指多个值相同的元素只分配一个存储空间,队零元素不分配存储空间。其目的为了节省空间
- 特殊矩阵
-
具有许多相同矩阵元素或零元素,并且这些相同元素或零元素的分布有一定规律。常见的特殊矩阵包括:对称矩阵,三角矩阵,对角矩阵。
-
对称矩阵
- 一个n阶方阵A[n] [n]中的元素满足A[i] [j] == A[j] [i],则称其为n阶对称矩阵。
- 对称矩阵中的元素关于主对角线对称,因此存储的时候只存储矩阵中上三角或者下三角矩阵,使得对称元素共享一个存储空间。
- 将这些元素按照下标,依次存储到数组中,那么数组下标与此矩阵的行列号有什么规律呢?下面以i表示矩阵的行号,j表示矩阵的列号,k表示数组的下标,且都以下三角存储为例:
则当矩阵的第一个元素以a[0] [0] 开始时,公式如下
当矩阵的第一个元素以a[1] [1] 开始时,公式如下
-
上三角矩阵/下三角矩阵
- 上三角矩阵:矩阵下三角部分(不包括对角线)元素全部为C,C可以是0.
- 下三角矩阵:矩阵上三角部分(不包括对角线)元素全部为C,C可以是0。
- 其存储方式和对称矩阵的存储方式一样,只需存储对角线及对角线一侧元素和对角线另一侧的元素C即可。
- 上三角矩阵:矩阵下三角部分(不包括对角线)元素全部为C,C可以是0.
-
对角矩阵
- 除主对角线以及其上下两条带状取余内的元素外,其余元素皆为C,C可以为0.
- 上图中的b为矩阵的半带宽,(2b+1)为矩阵的带宽。
- 同理,将此对角矩阵存入到数组中,有什么规律呢?下面以i表示矩阵的行号,j表示矩阵的列号,k表示数组的下标,以三对角矩阵为例:
则当矩阵的第一个元素以a[0] [0] 开始时,公式如下
-
则当矩阵的第一个元素以a[0] [0] 开始时,公式如下