数据结构-----复习(严蔚敏版)part2_栈

2024-05-12 19:38

本文主要是介绍数据结构-----复习(严蔚敏版)part2_栈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数据结构-----复习(严蔚敏版)part2_栈

栈和队列

    从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表,因此,可以成为限定性的数据结构。

栈的定义:

        栈是限定仅在表尾进行插入或删除操作的线性表。因此,对于栈来说,表尾端称为栈顶,相应的,表头端称为栈底。不含元素的空表称为空栈。
        特点:由于栈的修改是按后进先出的原则进行的,因此栈有称为后进先出的线性表。

栈的表示:

        与线性表类似,栈也有两种存储表示方法,顺序栈和链栈。
        顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元一次存放自栈底到栈顶的数据元素,同时附设指top指示栈顶元素在顺序中的位置。由于栈在使用过程中所需的最大空间的大小难以估计,因此,一般来说在初始化设空栈时不应限定栈的最大容量。合理的做法是:先为栈分配一个基本容量,然后在应用过程中,当栈的空间不够使用时在逐渐扩大,因此可以设定两个常量:存储空间初始分配量(STACK_INIT_SIZE)和存储空间分配增量(STACKINCREMENT),所以可以定义顺序栈:
    
typedef struct{SElemType  *base;    //栈底指针,在栈构造之前和销毁之后,base的为NULLSElemType   *top;     //栈顶指针int  stacksize;        //指示栈的当前可使用的最大容量}SqStack;

    基本操作:

Status InitStack(SqStack &S){//构造一个空栈SS.base = (SElemType *)malloc(STACK_INIT_SIZE *sizeof(SElemType));if(!S.base) exit(OVERFLOW);S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}Status GetTop(SqStack S, SElemType &e){//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERRORif(S.top == S.base)   return ERROR;e = *(S.top - 1);return OK;}Status Push(SqStack &S, SElemType e){if(S.top - S.base >= S.stacksize){    //栈满,追加存储空间S.base = (SElemType *) realloc (S.base,(S.stacksize + STACKINCREMENT) * sizeof(SElemType));if(!S.base) exit(OVERFLOW);S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}*S.top++ = e;return OK;}Status Pop(SqStack &S,SElemType &e){//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERRORif(S.top == S.base) return ERROR;e = * -- S.top;return OK;}

栈的应用举例:

1.数制转换

十进制数N和其他d进制数的转换,其中一个简单算法:N = (N div d) * d + N mod d    (其中:div为整除运算,mod为求余运算)
思想:由于计算过程是从低位到高位顺序产生八进制数的各个数位,而打印输出,一般来说应从高位到低位进行,恰好和计算过程相反,因此,若将计算过程中得到八进制数的各位顺序进栈,则按出栈序列打印输出的即为与输入对应的八进制数。
   void conversion(){//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数InitStack(S);scanf("%d",N);while(N){Push(S,N%8);N = N / 8;}while(!StackEmpty(s)){Pop(S,e) ;printf("%d",e);   }}

2.括号匹配的检验

    假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,即([]())或[([][])]等为正确的格式,[(])为不正确的格式。检验括号是否匹配的方法可用“期待的迫切程度”这个概念来描述。
思想:在算法中设置一个站,每读入一个括号,若是右括号,则或者使栈顶的最迫切的期待得以消解,或者是不合法的情况,若是左括号,则作为一个新的更迫切的期待压入栈中,自然是原有的在占中的所有为消解的期待的急迫性都降了一级,并且在算法的开始和结束,栈都应该是空的。
3.行编辑程序
    功能:接受用户从终端输入的程序或数据,并存入用户的数据区。由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的。较好的做法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。允许用户输入出差错,并在发现有误时及时更改。
    思想:设这个输入缓冲区为一个栈结构,每当从终端接受一个字符之后先作如下判别:如果它既不是退格符也不是退行符,则将该字符压入栈顶;如果是一个退格符,则从栈顶删去一个字符;如果他是一个退行符,则将字符栈清空。
       
 void LineEdit(){//利用字符栈S,从终端接受一行并传送至调用过程的数据区。InitStack(S);ch = getchar();while(ch != EOF){    //EOF为全文结束符while(ch != EOF && ch != '\n'){switch(ch){case '#' : Pop(S,c);    break;case '@' : CLearStack(S);    break;default  : Push(S,ch);    break;}ch = getchar();}将从栈栈底到栈顶的栈内字符传送至调用过程的数据区ClearStack(S);if(ch != EOF) ch = getchar();}DestroyStack(S);
}

3.迷宫求解

基本思想:假设“当前位置”指的是“在搜索过程中某一时刻所在图中某个方块位置”,则求迷宫中一条路径的算法的基本思想是:若当前位置“可通”,则纳入”当前路径“,并继续朝”下一位置“探索,即切换”下一位置“为”当前位置“,如此重复直至到达出口;若当前位置”不可通“,则应顺着”来向“退回到”前一通道块“,然后朝着除”来向“之外的其他方向继续探索;若该通道块的四周4个方块均”不可通“,则应从”当前路径“上删除该通道块。
假设以栈S记录”当前路径“,则栈顶中存放的是”当前路径上“最后一个通道块。由此,”纳入路径“的操作即为”当前位置入栈“;”从当前路径上删除前一通道块“的操作即为”出栈“。
typedef struct{int ord;    //通道块在路径上的”序号“PostType seat;    //通道块在迷宫中”坐标位置“int di;       //从通道块走向下一个通道块的”方向“
}SElemType        //栈的元素类型
Status MazePath(MazeType maze,PostType start,PostType end){//若迷宫maze中存在从入口start到出口end的通道。则求的一条存放在栈中(从栈底到栈顶),并且返回TRUE,否则返回FALSEInitStack(S);    curpos = start;curstep = 1;do{if(Pass(curpos)){    //当前位置可以通过,即是未曾走到过的通道块FootPrint(curpos);e = (curstep,curpos,1);Push(S,e);        //加入路径if(curpos == end)    return(TURE);curpos = NextPos(curpos,1);    //下一个位置是当前位置的东邻curstep++;    //探索下一步}else{    //当前位置不可通过if(!StackEmpty(S)){Pop(S,e);    //出栈while(e.di == 4 && !StackEmpty(S)){MarkPrint(e.seat);Pop(S,e);}if(e.di < 4){    //探索下一个方向e.di ++;    Push(S,e);curpos = NextPos(e.seat,e.di);    //设定当前位置是该新方向上的相邻块}}}}while(!StackEmpty(S));return (FALSE);
}

4.表达式求值

是栈应用的又一个典型例子。
为实现算符优先算法,可以使用两个工作栈。一个称作OPTR,用以寄存运算符;另一个称作OPND,用以寄存操作数或计算结果,基本思想:
    (1)首先置操作数栈为空栈,表达式起始符”#“为运算符栈的栈底元素;
    (2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后做相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为”#“)。
OperandType EvaluateExpression(){//算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合InitStack(OPTR);    Push(OPTR,'#');InitStack(OPND);    c = getchar();while(c != '#' || GetTop(OPTR) != '#'){if(! In(c, OP)) {Push(OPND, c); c = getchar();}    //不是运算符则进栈elseswitch (Precede(GetTop(OPTR), c)){    //比较输入的操作符和操作符栈栈顶的运算符优先级case '<' :       //栈顶元素优先权低
Push(OPTR, c); c = getchar();
break;  case '=':      //脱括号并接受下一个字符
Pop(OPTR, x); c = getchar();
break;case '>':       //退栈并将运算结果入栈
Pop(OPTR,theta);
Pop(OPND, b); Pop(OPND, a);
Push(OPND,Operate(a,theta,b));
break;}}return GetTop(OPND);
}

栈和递归的实现

Hanoi塔问题  

void hanoi(int n,char x, char y, char z){//将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘按规矩搬到塔座z上,y可用作辅助塔座。//搬动操作move(x,n,z)可定义为(c是初值为0的全局变量,对搬动计数),//printf("%i.move disk %i from %c to %c\n",++c,n,x,z);if(n == 1)move(x,1,z);else{hanoi(n-1,x,z,y);        //将x上编号为1至n-1的圆盘移到y,z作辅助塔move(x,n,z);            //将编号为n的圆盘从x移到zhanoi(n-1,y,x,z);       //将y上编号为1至n-1的圆盘移到z,x作辅助塔}
}

这篇关于数据结构-----复习(严蔚敏版)part2_栈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983553

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

Python 内置的一些数据结构

文章目录 1. 列表 (List)2. 元组 (Tuple)3. 字典 (Dictionary)4. 集合 (Set)5. 字符串 (String) Python 提供了几种内置的数据结构来存储和操作数据,每种都有其独特的特点和用途。下面是一些常用的数据结构及其简要说明: 1. 列表 (List) 列表是一种可变的有序集合,可以存放任意类型的数据。列表中的元素可以通过索

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

【数据结构入门】排序算法之交换排序与归并排序

前言         在前一篇博客,我们学习了排序算法中的插入排序和选择排序,接下来我们将继续探索交换排序与归并排序,这两个排序都是重头戏,让我们接着往下看。  一、交换排序 1.1 冒泡排序 冒泡排序是一种简单的排序算法。 1.1.1 基本思想 它的基本思想是通过相邻元素的比较和交换,让较大的元素逐渐向右移动,从而将最大的元素移动到最右边。 动画演示: 1.1.2 具体步

数据结构:线性表的顺序存储

文章目录 🍊自我介绍🍊线性表的顺序存储介绍概述例子 🍊顺序表的存储类型设计设计思路类型设计 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾” 和“内容共创官” ,现在我来为大家介绍一下有关物联网-嵌入

[数据结构]队列之顺序队列的类模板实现

队列是一种限定存取位置的线性表,允许插入的一端叫做队尾(rear),允许删除的一端叫做队首(front)。 队列具有FIFO的性质 队列的存储表示也有两种方式:基于数组的,基于列表的。基于数组的叫做顺序队列,基于列表的叫做链式队列。 一下是基于动态数组的顺序队列的模板类的实现。 顺序队列的抽象基类如下所示:只提供了接口和显式的默认构造函数和析构函数,在派生类中调用。 #i