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

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

栈的顺序存储结构也叫作顺序栈,对于栈顶指针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. gdb pretty printer for STL debug in Linux

    Check your gcc version. If it is less than 4.7, you need use another printer.py file. Get the file f ...

  2. coursera-斯坦福-机器学习-吴恩达-笔记week1

    1 Introduction 1.1 概念:一个程序被认为能从经验E中学习,解决任务 T,达到性能度量值P,当且仅当, 有了经验E后,经过P评判, 程序在处理 T 时的性能有所提升. 1.2 机器学习 ...

  3. Python---遍历序列的各种方式

    本文主要列举使用for循环遍历类似list结果的方式,因为老是使用for e in w_list真的是太没创意了,这显然不是我的风格,嘿嘿... 1. for item in s: 遍历s中的元素 2 ...

  4. oracle项目案例脚本

    前言:这是我从其他地方找到的一个oracle的案例脚本,在自己使用数据库的时候方便使用. -- 01 创建表空间 -- 注意表空间的路径 根据实际安装环境进行调整 CREATE TABLESPACE ...

  5. Invalid demension,shape[-1,40,40,1]

    代码里定一个了没有用的placeholder, 或者说没有给这个placeholder 传值

  6. CHECK约束表达式

    1.性别:只能填写'男'和'女' (字段名='男'or 字段名='女') 注意:单引号里的值可以为其他任何字 2.规定密码长度不能小于6位数 (len([字段名])>(5))   3.例:成绩在 ...

  7. makeObjectsPerformSelector对数组中的对象发送消息执行对象中方法

    - (void)makeObjectsPerformSelector:(SEL)aSelector; - (void)makeObjectsPerformSelector:(SEL)aSelector ...

  8. python的format格式化

    使用方法:  '{}bbccc'.format(aa) = aabbcc, 用来代替python2中的%,即替换. 1.通过位置来指定替换 In [2]: '{0},{1}'.format('a', ...

  9. python2入门(2)

    四.python条件语句 if语句基本语法if 判断条件: 执行语句块else if: 执行语句块else: 执行语句 五.循环语句 1 - while循环基本语法while 判断条件: 执行语句块w ...

  10. 使用flask框架实现web页面与数据库数据互联+常见的几种状态码

    1.通过cygwin从pip install两个包:PyMySQL.SQLAlchemy: 2.在app.py中import我们要用到的库中的包:create_engine,text :from sq ...