之前我们学过了普通的线性表,接下来我们来了解一下两种特殊的线性表——栈和队列。

栈是只允许在一端进行插入或删除的线性表。

栈的顺序存储结构也叫作顺序栈,对于栈顶指针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语言数据结构基础学习笔记——栈和队列的更多相关文章

  1. C语言数据结构基础学习笔记——树

    树是一种一对多的逻辑结构,树的子树之间没有关系. 度:结点拥有的子树数量. 树的度:树中所有结点的度的最大值. 结点的深度:从根开始,自顶向下计数. 结点的高度:从叶结点开始,自底向上计数. 树的性质 ...

  2. C语言数据结构基础学习笔记——B树

    2-3树:是一种多路查找树,包含2结点和3结点两种结点,其所有叶子结点都在同一层次. 2结点:包含一个关键字和两个孩子(或没有孩子),其左孩子的值小于该结点,右孩子的值大于该结点. 3结点:包含两个关 ...

  3. C语言数据结构基础学习笔记——C语言基础

    抽象数据类型(ADT)是指一个数学模型以及定义在该模型上的一组操作,通常用(数据对象,数据关系,基本操作集)这样的三元组来表示抽象数据类型. 数据结构是相互之间存在一种或多种特定关系的数据元素的集合, ...

  4. C语言数据结构基础学习笔记——动态查找表

    动态查找表包括二叉排序树和二叉平衡树. 二叉排序树:也叫二叉搜索树,它或是一颗空树,或是具有以下性质的二叉树: ①若左子树不空,则左子树上所有结点的值均小于它的根结点的值: ②若右子树不空,则右子树上 ...

  5. C语言数据结构基础学习笔记——静态查找表

    查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找. 查找表:用于查找的数据集合称为查找表,一般有以下操作:①查找是否在表中:②查找属性:③进行操作. 查找表又分为: ①静态查找表:只可以进行 ...

  6. C语言数据结构基础学习笔记——图

    图(G)由顶点集(V)和边集(E)组成,G=(V,E) 常用概念: ①V(G)表示图G中顶点的有限非空集,V永不为空: ②用|V|表示图G中顶点的个数,也称为图G的阶: ③E(G)表示图G中顶点之间关 ...

  7. C语言数据结构基础学习笔记——基础线性表

    线性表是指具有相同数据类型的n(n>=0)个数据元素的有限序列,它具有一个表头元素和一个表尾元素,并且每一个数据元素最多只有一个直接前驱和一个直接后继. 线性表的顺序存储也叫作顺序表,它的特性是 ...

  8. C语言数据结构——第三章 栈和队列

    三.栈和队列 栈和队列是两种重要的线性结构.从数据结构的角度来看,栈和队列也是线性表,它的特殊性在于栈和队列的基本操作是线性表操作的子集,它们的操作相对于线性表来说是受到限制的,因此,可以称其为限定性 ...

  9. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

随机推荐

  1. zabbix3.4.7官方解释触发器

    函数   描述 参数 说明 abschange   最近获取值与之前获取值差的绝对值.   支持值的类型: float, int, str, text, log 例如: (最近获取值;之前获取值=ab ...

  2. java替换字符串中的World为Money

    public class Money{ public static void main(String[] args) { String a = "Hello Java World\n&quo ...

  3. 微服务-封装-docker by daysn大雄

    目录 序言一.什么是容器二.docker入门 2.1安装启动2.2docker使用 2.2.1 helloworld 2.2.2 容器 2.2.3 镜像 2.2.4 容器的连接     序言 虚拟化一 ...

  4. vue+canvas踩坑之旅

    let img=new Image(); if(img.complete) { console.log('dd'); } img.src="http://localhost:8888/sta ...

  5. centos安装ruby

    下面开始安装Ruby 一.下载Ruby源码包 wget ftp://ftp.ruby-lang.org/pub/ruby/2.1/ruby-2.1.7.tar.gz 二.解压安装Ruby tar zx ...

  6. re模块+面向对象

    re模块 re:其实就是带有特殊语法的字符串 语法:单个字符和多个字符 单个字符: \d是匹配所有的数字 \D是匹配所有的非数字 \s是所有的换行符,制表符,空白等,回车符 \S是所有费换行符,空白和 ...

  7. Java语法基础学习DayThirteen(枚举类和注解)

    一.枚举类 1.概述:即一个类中只能有有限个对象,若只有一个对象,则可以作为单例模式的一种实现. 2.自定义枚举类(JDK1.5以前这么做) //枚举类 class Season{ //1.提供类的属 ...

  8. oh_my_zsh

    oh_my_zsh  zsh默认已经安装   cat /etc/shells   查看安装没有   (https://xiaozhou.net/learn-the-command-line-iterm ...

  9. 剑指Offer 2. 替换空格 (字符串)

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 题目地址 https://ww ...

  10. Couldn't find preset "es2015" relative to directory问题解决

    由于是菜鸟没使用ES标准,而引入的vue-ueditor使用了ES标准,所以编译会报错,解决办法如下: npm install babel-preset-es2015 --save-dev 然后需要在 ...