C语言数据结构基础学习笔记——栈和队列
之前我们学过了普通的线性表,接下来我们来了解一下两种特殊的线性表——栈和队列。
栈是只允许在一端进行插入或删除的线性表。
栈的顺序存储结构也叫作顺序栈,对于栈顶指针top,当栈为空栈时,top=-1;当栈为满栈时,top=MaxSize-1。顺序栈的定义为:
#define MaxSize 50 //定义栈中元素的最大个数
typedef struct{
Elemtype data[MaxSize]; //存放栈中元素
int top; //栈顶指针
}SqStack; //顺序栈的简写
顺序栈的入栈操作为:
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-) return false;
S.data[++S.top]=x; return true;
}
顺序栈的出栈操作为:
bool Pop(SqStack &S,ElemType &x){
if(S.top==-) return false;
x=S.data[S.top--];
return true;
}
顺序栈读取栈顶元素为:
bool GetTop(SqStack S,ElemType &x){
if(S.top==-) return false;
x=S.data[S.top];
return true;
}
顺序栈读取栈顶元素与出栈操作对比,注意读取栈顶元素时栈顶指针没有自减。
对于一个数组,如果只从数组头部开始入栈,并没有达到很高的空间利用率,因此我们引入共享栈的概念。共享栈是两个栈共用同一个数组,分别从数组头部和数组尾部开始开始入栈。其定义为:
#define MaxSize 100 //定义栈中元素的最大个数
typedef struct{
Elemtype data[MaxSize]; //存放栈中元素
int top1; //栈1顶指针
int top2; //栈2顶指针
}SqDoubleStack; //共享栈的简写
bool Push(SqStack &S,ElemType x,int stackNum){
if(S.top1+==S.top2) return false;
if(stackNum==) S.data[++S.top1]=x;
else if(stackNum==) S.data[--S.top2]=x;
return true;
}
共享栈的满栈条件是top1+1=top2。
同时,栈也有链式存储结构,叫作链栈,它空栈时top=NULL,一般不会满栈。链栈的定义为:
typedef struct SNode{
ElemType data; //数据域
struct SNode *next; //指针域
}SNode,*SLink; //链式栈的结点
typedef struct LinkStack{
SLink top; //栈顶指针
int count; //链式栈结点数
}LinkStack;
栈有着丰富的应用场景,比较经典的题目有括号的匹配以及后缀表达式的求值。
①括号的匹配:给你一串杂乱的大,中,小括号的序列,让你判断这里的括号序列满不满足数学计算的规律(括号套括号)。主要思路是将所有的左括号依次入栈,碰到右括号出栈匹配,若是不同种的括号返回false,若是同一种括号则继续以上操作,直到空栈并且数组中的字符串遍历完成,返回true。
②后缀表达式的计算:后缀表达式是计算机最喜欢的一种表达式方式,例如(5+10+1*13)/14这个中缀表达式,它的后缀表达式为5 10 + 1 13 * + 14 /,其将每一步计算的运算符号置后。利用栈计算后缀表达式的主要思路是:①将数字5入栈,再将数字10入栈;②当指针碰到运算符+时,将栈中的前两个元素出栈进行计算(后出栈的数在前位),结果入栈,如本例值15入栈;③同上一步,计算1*13得13入栈,此时栈底值15,栈顶值13;④同上一步,指针碰到运算符+,将15与13求和,得值28入栈;⑤再同上一步,计算28/14=2入栈;⑥此时字符串数组遍历完毕,栈中的唯一值2则为表达式的结果。
栈思想的最重要的一个应用便是递归,递归是指在一个函数、过程或数据结构中的定义中又应用了它自身的编程思想。理解递归的一个基础方法便是找到递归式和递归边界,我们来看两个例子:
①用递归求n的阶乘:
int F(int n){
if(n==) return ; //递归边界
else return n*F(n-); //递归式
}
②求斐波那契数列的第n项:
int Fib(int n){
if(n==) return ; //递归边界
else if(n==) return ; //递归边界
else return Fib(n-)+Fib(n-); //递归式
}
递归式是每一次递归过程的计算核心,而递归边界就是每一次递归的结束标志。
另一种特殊的线性表是队列,队列的定义是只允许在一端进行插入,而在另一端进行删除的线性表。
队列的顺序存储结构是顺序队列,其定义为:
#define MaxSize 50 //定义队列中元素的最大个数
typedef struct{
Elemtype data[MaxSize]; //存放队列中元素
int front,rear; //队头指针和队尾指针
}SqQueue;
但对于一个数组队列来说,每一次入队和出队都会浪费一个数组位置,于是我们引入循环队列的概念,队尾指针rear在指到队尾后会回到下标为0的位置(利用取余来实现),即每一次rear和front的更新基于以下操作:rear=(rear+1)%MaxSize,front=(front+1)%MaxSize。
但是这样又产生了新的问题,rear=front到底是队空还是队满无法判断。这样的问题有以下两种解决办法:①设一个frag,作为标志位,当队满时frag=1;②牺牲一个数组位置,保留一个空余单元,此时队满的判断标准变成了(rear+1)%MaxSize=front,队列中的元素数计算方法为:(rear-front+MaxSize)%MaxSize。
循环队列的入队操作为:
bool EnQueue(SqQueue &Q,ElemType x){
if((Q.rear+)%MaxSize==Q.front) return false; //队满
Q.data[Q.rear]=x;
Q.rear=(Q.rear+)%MaxSize;
return true;
}
循环队列的出队操作为:
bool DeQueue(SqQueue &Q,ElemType &x){
if(Q.rear==Q.front) return false; //队空
x=Q.data[Q.front];
Q.front=(Q.front+)%MaxSize;
return true;
}
队列链式存储的定义为:
typedef struct{
ElemType data; //数据域
struct LinkNode *next; //指针域
}LinkNode; //链式队列的结点
typedef struct{
LinkNode *front,*rear; //队头和队尾指针
}LinkQueue;
链式队列的入队和出队类似于链表的相应操作。
C语言数据结构基础学习笔记——栈和队列的更多相关文章
- C语言数据结构基础学习笔记——树
树是一种一对多的逻辑结构,树的子树之间没有关系. 度:结点拥有的子树数量. 树的度:树中所有结点的度的最大值. 结点的深度:从根开始,自顶向下计数. 结点的高度:从叶结点开始,自底向上计数. 树的性质 ...
- C语言数据结构基础学习笔记——B树
2-3树:是一种多路查找树,包含2结点和3结点两种结点,其所有叶子结点都在同一层次. 2结点:包含一个关键字和两个孩子(或没有孩子),其左孩子的值小于该结点,右孩子的值大于该结点. 3结点:包含两个关 ...
- C语言数据结构基础学习笔记——C语言基础
抽象数据类型(ADT)是指一个数学模型以及定义在该模型上的一组操作,通常用(数据对象,数据关系,基本操作集)这样的三元组来表示抽象数据类型. 数据结构是相互之间存在一种或多种特定关系的数据元素的集合, ...
- C语言数据结构基础学习笔记——动态查找表
动态查找表包括二叉排序树和二叉平衡树. 二叉排序树:也叫二叉搜索树,它或是一颗空树,或是具有以下性质的二叉树: ①若左子树不空,则左子树上所有结点的值均小于它的根结点的值: ②若右子树不空,则右子树上 ...
- C语言数据结构基础学习笔记——静态查找表
查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找. 查找表:用于查找的数据集合称为查找表,一般有以下操作:①查找是否在表中:②查找属性:③进行操作. 查找表又分为: ①静态查找表:只可以进行 ...
- C语言数据结构基础学习笔记——图
图(G)由顶点集(V)和边集(E)组成,G=(V,E) 常用概念: ①V(G)表示图G中顶点的有限非空集,V永不为空: ②用|V|表示图G中顶点的个数,也称为图G的阶: ③E(G)表示图G中顶点之间关 ...
- C语言数据结构基础学习笔记——基础线性表
线性表是指具有相同数据类型的n(n>=0)个数据元素的有限序列,它具有一个表头元素和一个表尾元素,并且每一个数据元素最多只有一个直接前驱和一个直接后继. 线性表的顺序存储也叫作顺序表,它的特性是 ...
- C语言数据结构——第三章 栈和队列
三.栈和队列 栈和队列是两种重要的线性结构.从数据结构的角度来看,栈和队列也是线性表,它的特殊性在于栈和队列的基本操作是线性表操作的子集,它们的操作相对于线性表来说是受到限制的,因此,可以称其为限定性 ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
随机推荐
- python中如何删除列表中的所有元素
今天写代码的时候遇到一个小问题,Python中要删除列表中的所有元素.Python本身就提供了pop.remove.del这些删除的函数.我想着用循环实现,结果很麻烦.几番周折上了stackoverf ...
- Spring Boot的事务管理注解@EnableTransactionManagement的使用
@EnableTransactionManagement:负责开启springboot 的事物支持,等同于xml配置文件中的 <tx:annotation-driven /> 然后在访问数 ...
- 磁性窗体设计C#(二)
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- java正则表达式appendReplacement和appendTail方法
appendReplacement是java中替换相应字符串的一个方法 appendReplacement(StringBuffer sb,String replacement) 将当前匹配子串替换为 ...
- 大大维的游戏机计划1--贪吃蛇v1
本文为大大维原创,最早于博客园发表,转载请注明出处!!! 虽然本人一直是个免费的游戏测试员(/手动滑稽),但一直有着一个游戏架构师的梦想.正如马爸爸所说,梦想还是要有的,万一实现了呢? 这些天放寒假, ...
- 如何用Caffe训练自己的网络-探索与试验
现在一直都是用Caffe在跑别人写好的网络,如何运行自定义的网络和图片,是接下来要学习的一点. 1. 使用Caffe中自带的网络模型来运行自己的数据集 参考 [1] :http://www.cnblo ...
- linux日常命令之二
ps -ef 查看当前系统所有进程,ps 进程查看命令,-e 显示所有进程,-f 全格式. free -h 查看系统实际使用内存的情况. 显示格式为: total used f ...
- Web服务器之Nginx详解(理论部分)
大纲 一.前言 二.Web服务器提供服务的方式 三.多进程.多线程.异步模式的对比 四.Web 服务请求过程 五.Linux I/O 模型 六.Linux I/O 模型具体说明 七.Linux I/O ...
- robot framework程序运行过程中,遇到点击事件之后,未出现点击之后的效果(求解)
1.click Element操作,在实际过程中偶然会出现,日志显示已点击成功,但是实际自动化页面,没有点击成功之后的操作 现象: 现象描述:程序执行到点击侧边栏的[人员信息]之后,日志显示已经点击成 ...
- xamarin C# 安卓实现 ListView 放大缩小
翻译自java示例https://raw.githubusercontent.com/Xjasz/AndroidZoomableViewGroup/master/ZoomListView.java u ...