408数据结构知识点——第三章 栈、队列和数组(二)

文章目录

    • 栈和队列的应用
      • 括号匹配
        • 代码实现
      • 表达式求值
        • 代码实现
      • 栈在递归中的应用
      • 队列的应用
        • 舞伴问题
        • 树的层次遍历
        • 图的广度优先遍历
        • 操作系统处理机调度策略
    • 数组和特殊矩阵
      • 数组的存储结构
        • 一维数组
        • 二维数组
      • 普通矩阵的存储
        • 对称矩阵的压缩存储
        • 三角矩阵的压缩存储
        • 三对角矩阵的压缩存储
        • 稀疏矩阵的压缩存储

注:内容参考王道2024考研复习指导以及《数据结构》

栈和队列的应用

括号匹配

问题

假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,即:

  1. ( [ ] ( ) )或[ ( [ ] [ ] ) ]为正确格式;
  2. [ ( ] )为错误格式;
  3. ( [ ( ) )或( ( ) ] )为错误格式。

分析

可用实现该特性。最后出现的左括号最先被匹配(LIFO),每出现一个右括号,就 “消耗”一个左括号。

依次扫描所有字符,遇到左括号入栈,遇到右括号则弹出栈顶元素检查是否匹配。

匹配失败情况:①左括号单身②右括号单身③左右括号不匹配。

算法流程图

408数据结构知识点——第三章 栈、队列和数组(二)_第1张图片

代码实现
bool bracketCheck(char str[],int length){
    SqStack S;
    InitStack(S);
    for(int i=0;i

表达式求值

算数表达式由三部分组成:

  • 操作数(operand):常数、标识符
  • 表达式运算符(operator):算术、逻辑、关系
  • 界限符(delimiter):括号、结束符

表达式分为三种:

  • 中缀表达式:运算符在两个操作数中间
  • 后缀表达式(逆波兰式):运算符在两个操作数后面
  • 前缀表达式(波兰式):运算符在两个操作数前面
代码实现

中缀表达式转后缀

初始化一个栈,用于保存暂时还不能确定运算顺序的运算符。

从左到右处理各个元素,直到末尾。可能遇到三种情况:

  1. 遇到操作数。直接加入后缀表达式。
  2. 遇到界限符。遇到“(”直接入栈;遇到“)”则依次弹出栈内运算符并加入后缀表达式,直到弹出“(”为止。注意:“(”不加入后缀表达式。
  3. 遇到运算符。依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到“(” 或栈空则停止。之后再把当前运算符入栈。

按上述方法处理完所有字符后,将栈中剩余运算符依次弹出,并加入后缀表达式。

用栈实现后缀表达式的计算

  1. 从左往右扫描下一个元素,直到处理完所有元素;
  2. 若扫描到操作数则压入栈,并回到1;否则执行2;
  3. 若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶,回到1;
  4. :先出栈的是右操作数

若计算前缀表达式,则应该从右往左扫描,其余与计算后缀表达式相同,注意先出栈的是左操作数

算符间的优先关系

408数据结构知识点——第三章 栈、队列和数组(二)_第2张图片

OperandType EvaluateExpression(){
    SqStack OPTR,OPND;
    InitStack (OPTR);//运算符栈
    Push(OPTR,'#') ;
    InitStack (OPND);//操作数栈
    ch=getchar();
    while (ch!= '#' || GetTop(OPTR)! = '#') {
        if (! In(ch)){
            Push(OPND,ch); ch=getchar();
        } // ch不是运算符则进栈
    else
        switch (Precede(GetTop(OPTR),ch)) {//比较优先权
            case '<' : //当前字符ch压入OPTR栈,读入下一字符ch
                Push(OPTR, ch);
                ch = getchar();
                break;
            case '>' ://弹出OPTR栈顶的运算符运算,并将运算结果入栈
                Pop(OPTR, theta);
                Pop(OPND, b);
                Pop(OPND, a);
                Push(OPND,Operate(a, theta, b));
                break;
            case '=' :    //脱括号并接收下一字符
                Pop(OPTR,x);
                ch = getchar();
                break;
        } // switch
  } // while
    return GetTop(OPND);
} // EvaluateExpression

栈在递归中的应用

函数调用的特点:最后被调用的函数最先执行结束(LIFO)。

函数调用时,需要用一个栈存储:

  1. 调用返回地址
  2. 实参
  3. 局部变量

递归调用时,函数调用栈可称为“递归工作栈”,每进入一层递归,就将递归调用所需信息压入栈顶;每退出一层递归,就从栈顶弹出相应信息。

缺点:效率低,太多层递归可能会导致栈溢出;可能包含很多重复计算。

队列的应用

舞伴问题

问题:假设在舞会上,男士和女士各自排成一队。舞会开始时,依次从男队和女队的对头各出一人配成舞伴。如果两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。现要求写以算法模拟上述舞伴配对问题。

分析:显然,先入队的男士或女士先出队配成舞伴。因此该问题具有典型的先进先出特征,可以利用队列作为算法的数据结构。首先构造两个队列依次从队头元素出队配成舞伴某队为空,则另外一对等待着则是一下舞曲第一个可获得舞伴的人。

树的层次遍历
图的广度优先遍历
操作系统处理机调度策略

数组和特殊矩阵

数组的存储结构

一维数组

408数据结构知识点——第三章 栈、队列和数组(二)_第3张图片

各数组元素大小相同,且物理上连续存放。

数组元素a[i] 的存放地址 = L O C + i ∗ s i z e o f ( E l e m T y p e ) ( 0 ≤ i < 10 ) = LOC + i * sizeof(ElemType) (0≤i<10) =LOC+isizeof(ElemType)(0i<10)

:除非题目特别说明,否则数组下标默认从0开始 注意审题!

二维数组

408数据结构知识点——第三章 栈、队列和数组(二)_第4张图片

行优先存储:M行N列的二维数组中,则

b{i,j}的存储地址 = L O C + ( i ∗ N + j ) ∗ s i z e o f ( E l e m T y p e ) = LOC + (i*N + j) * sizeof(ElemType) =LOC+(iN+j)sizeof(ElemType)

列优先存储:M行N列的二维数组中,则

b{i,j}的存储地址 = L O C + ( j ∗ M + i ) ∗ s i z e o f ( E l e m T y p e ) = LOC + ( j*M+ i ) * sizeof(ElemType) =LOC+(jM+i)sizeof(ElemType)

普通矩阵的存储

对于普通矩阵可用二维数组存储,但是某些特殊矩阵可以压缩存储空间。

对称矩阵的压缩存储

若 n 阶方阵中任意一个元素 a i , j a_{i,j} ai,j都有 a i , j = a j , i a_{i,j} = a_{j,i} ai,j=aj,i,则该矩阵为对称矩阵。

408数据结构知识点——第三章 栈、队列和数组(二)_第5张图片

压缩存储策略:只存储主对角线+下三角区(或主对角线+上三角区)。按行优先原则将各元素存入一维数组中。

image-20240120141244379

从矩阵下标推出一维数组下标,即 a i , j ( i ≥ j ) → B [ k ] a_{i,j}(i \geq j) \rightarrow B[k] ai,j(ij)B[k],则有 k = i ( i − 1 ) 2 + j − 1 k=\frac{i(i-1)}{2}+j-1 k=2i(i1)+j1
出题方法

  • 存储上三角?下三角?
  • 行优先?列优先?
  • 矩阵元素的下标从0?1?开始
  • 数组下标从0?1?开始
三角矩阵的压缩存储

下三角矩阵:除了主对角线和下三角区,其余的元素相同

上三角矩阵:除了主对角线和上三角区,其余的元素相同

408数据结构知识点——第三章 栈、队列和数组(二)_第6张图片

压缩存储策略:按行优先原则将橙色区元素存入一维数组中。并在最后一个位置存储常量c。

image-20240120142102069

从矩阵下标推出一维数组下标,即 a i , j ( i ≥ j ) → B [ k ] a_{i,j}(i \geq j) \rightarrow B[k] ai,j(ij)B[k],则有

  • 下三角矩阵KaTeX parse error: Undefined control sequence: \mbox at position 56: …-1)}{2}+j-1 & \̲m̲b̲o̲x̲{for} & i \leq…

  • 上三角矩阵KaTeX parse error: Undefined control sequence: \mbox at position 65: …)}{2}+(j-i) & \̲m̲b̲o̲x̲{for} & i \leq…

三对角矩阵的压缩存储

408数据结构知识点——第三章 栈、队列和数组(二)_第7张图片

压缩存储策略:按行优先(或列优先)原则,只存储带状部分

image-20240120143230405

从矩阵下标推出一维数组下标,即 a i , j ( i ≥ j ) → B [ k ] a_{i,j}(i \geq j) \rightarrow B[k] ai,j(ij)B[k],则有 k = 2 i + j − 3 k=2i+j-3 k=2i+j3

若已知数组下标k如何得到i,j?

分析:前i-1行共 3(i-1)-1 个元素,前i行共 3i-1 个元素,显然, 3(i-1)-1 < k+1 ≤ 3i-1

image-20240120143629799

稀疏矩阵的压缩存储

408数据结构知识点——第三章 栈、队列和数组(二)_第8张图片

压缩存储策略

  • 顺序存储——三元组 <行,列,值>
  • 十字链表法

408数据结构知识点——第三章 栈、队列和数组(二)_第9张图片

你可能感兴趣的:(数据结构,考研,学习)