第三章 栈和队列【数据结构与算法】1

简介: 第三章 栈和队列【数据结构与算法】1

配套资源下载

数据结构资源下载导航【数据结构】

第 3 章 栈和队列

第2章介绍了线性表的概念,从数据结构上看,栈和队列也是线性表,只不过是两种特殊的 线性表。栈只允许在表的一端进行插入或删除操作,而队列只允许在表的一端进行插入操作、在另一端进行删除操作。因而,栈和队列也可以被称为操作受限的线性表。从数据类型的角度来看,栈与队列是与线性表不同的抽象数据结构。

3.1 应用实例

应用实例一 迷宫求解问题

这是实验心理学中的一个经典问题,心理学家用一个无顶盖的大盒子做成“迷宫”从然后把一只老鼠从入口处赶进迷宫。迷宫中设置了很多隔断,对老鼠的前进方向构成多处障碍,在迷宫的唯一出口处放置了一块奶酪,吸引老鼠寻找正确的通路以到达出口。


可以用一个mxn的方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计

一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得到没有通路的结论。


计算机解迷宫时,通常是采用“穷举求解”的方法,即从入口出发,沿某方向向前探索,若能 走通则继续往前走;否则沿原路返回,换一个方向再继续探索,直至所有可能的通路都探索到为止。为了保证在任何位置上都能沿原路退回,显然要用具有后进先出特性的栈来保存从入口到当前位置的路径。

应用实例二“马”踏棋盘问题

将棋子“马”随机地放在国际象棋8x8棋盘Board[8][8]的某个方格中,“马”按走棋规则进 行移动,要求每个方格只进入一次,走遍棋盘上所有的64个方格。编写(非)递归程序,求出“马” 的行走路线,并按求出的行走路线将数字1,2,…,64依次填入一个8x8的方阵并输出。


求解时可采用栈的数据结构,即将“马”的行走顺序压人栈中。每次在多个可走的位置中选 择其中一个进行试探,其余未曾试探过的可走位置必须用适当的结构妥善管理,以备试探失败时 的“回溯”(悔棋)使用。

以上实例的分析与实现将在3.4节详细介绍。

3.2栈

3.2.1 栈的概念及运算

栈(stack)是一种只允许在一端进行插人和删除操作的线性表,它是一
种操作受限的线性表

在表中允许进行插入和删除的一端称为“栈顶”(top),另一端称为“栈底”(bottom)。

栈的插入操作通常称为“入栈”或“进栈”(push),

而栈的删除操作则称为“出栈”或“退栈”(pop)。

当栈中无数据元素时,称为“空栈”。

栈具有后进先出的特性,因此又称为“后进先出”(Last In First Out,LIFO)表

栈的示意图



栈的基本运算有以下几种。
① InitStack(S) 初始化:初始化一个新的栈。
② Empy(S )栈的非空判断:若栈S不空,则返回TRUE;否则,返回FALSE。
③ Push(S.x) 入楼:在栈S的顶部插入元素x,若栈满,则返回FALSE;否则,返回TRUE
④ Pop(S) 出栈:若栈S不空,则返回栈顶元素,并从栈顶中删除该元素;否则,返回空元素  
⑤ GetTop(S) 取栈顶元素:若栈S不空,则返回栈顶元素;否则返回空元素NULL。
⑥ SetEmpty(S) 置栈空操作:置栈S为空栈。

栈是一种特殊的线性表,因此栈可采用顺序存储结构存储,也可以使用链式存储结构存储。

3.2.2栈的顺序存储结构

1. 顺序栈

利用顺序存储的方式实现的栈称为“顺序栈”。类似于顺序表的定义,栈中的数据元素用一个
预设的足够长度的一维数组来实现:ElemType elem[MAXSIZE]。栈底位置可以设置在数组任
一个端点,而栈顶是随着插人和删除而变化的。用int top来作为栈顶的指针,指明当前栈顶的    位置,同时将elem和top封装在一个结构中。顺序栈的类型描述如下。  
#define MAXSIZE<栈最大元素数>
typedef struct{ 
  ElemType elem[MAXSIZE];
  int top;
}SeqStack;

定义一个指向顺序栈的指针:

SeqStack *s;

常将0下标端设为栈底,这样空栈时校顶指针s->top=-1;入栈时,栈顶指针加1,即s->top++;出栈时,栈顶指针减1,即s->top–。

栈的基本操作如下

相关代码请看配套资源

1-顺序栈.c

#include<stdio.h> 
#include<stdlib.h> 
int main(){
  SeqStack *s=InitStack();
  printf("%d",Empty(s));//1 
  int x1=1;
  Push(s,x1);
  int x2=2;
  Push(s,x2);
  printf("%d",Empty(s));//0
  int x3;
  Pop(s,&x3);
  printf("%d",x3);//2
  int t=GetTop(s);
  printf("%d",t);//1
}

运行结果如下



2. 多栈共享邻接空间

栈的共享中最常见的是两栈共享
假设两个栈共享一维数组elem[MAXSIZE],则可以利用栈的“栈底位置不变,栈顶位置动态变化”特性,两个栈底分别为-1和MAXSIZE,而它们的栈顶都往中间方向延伸。因此,只要整个数组elem[MAXSIZE]未被满,无论哪个栈的人栈都不会发生上溢。


两栈共享的数据结构可定义如下。

typedef struct{
  ElemType elem[ MAXSIZE];
  int lefttop;//左栈栈顶位置指示器
  int righttop;//右栈栈顶位置指示器
} Dupsqstack;

两个栈共享邻接空间的示意图如图3-4所示。左栈入栈时,栈顶指针加1,右栈人栈时,栈顶指针减1。由于两个栈顶均可向中间伸展,互补余缺,因此使得每个栈的最大空间均大于MAXSIZE/2。


为了识别左右栈,必须另外设定标志:

char status;
status ='L';  //左栈
status ='R';//右栈

在进行栈操作时,需指定栈号status=L’为左栈,status='R’为右栈;判断栈满的条件如下:

s->lefttop+1=s->righttop;
相关文章
|
10天前
|
存储 Java
【数据结构】优先级队列(堆)从实现到应用详解
本文介绍了优先级队列的概念及其底层数据结构——堆。优先级队列根据元素的优先级而非插入顺序进行出队操作。JDK1.8中的`PriorityQueue`使用堆实现,堆分为大根堆和小根堆。大根堆中每个节点的值都不小于其子节点的值,小根堆则相反。文章详细讲解了如何通过数组模拟实现堆,并提供了创建、插入、删除以及获取堆顶元素的具体步骤。此外,还介绍了堆排序及解决Top K问题的应用,并展示了Java中`PriorityQueue`的基本用法和注意事项。
21 5
【数据结构】优先级队列(堆)从实现到应用详解
|
1天前
|
存储 算法 前端开发
深入理解操作系统:进程调度与优先级队列算法
【9月更文挑战第25天】在操作系统的复杂世界中,进程调度是维持系统稳定运行的核心机制之一。本文将深入探讨进程调度的基本概念,分析不同的进程调度算法,并着重介绍优先级队列算法的原理和实现。通过简洁明了的语言,我们将一起探索如何优化进程调度,提高操作系统的效率和响应速度。无论你是计算机科学的初学者还是希望深化理解的专业人士,这篇文章都将为你提供有价值的见解。
|
1天前
|
存储
|
16天前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
|
18天前
|
存储 C语言
数据结构基础详解(C语言): 栈与队列的详解附完整代码
栈是一种仅允许在一端进行插入和删除操作的线性表,常用于解决括号匹配、函数调用等问题。栈分为顺序栈和链栈,顺序栈使用数组存储,链栈基于单链表实现。栈的主要操作包括初始化、销毁、入栈、出栈等。栈的应用广泛,如表达式求值、递归等场景。栈的顺序存储结构由数组和栈顶指针构成,链栈则基于单链表的头插法实现。
119 3
|
19天前
|
Java
【数据结构】栈和队列的深度探索,从实现到应用详解
本文介绍了栈和队列这两种数据结构。栈是一种后进先出(LIFO)的数据结构,元素只能从栈顶进行插入和删除。栈的基本操作包括压栈、出栈、获取栈顶元素、判断是否为空及获取栈的大小。栈可以通过数组或链表实现,并可用于将递归转化为循环。队列则是一种先进先出(FIFO)的数据结构,元素只能从队尾插入,从队首移除。队列的基本操作包括入队、出队、获取队首元素、判断是否为空及获取队列大小。队列可通过双向链表或数组实现。此外,双端队列(Deque)支持两端插入和删除元素,提供了更丰富的操作。
23 0
【数据结构】栈和队列的深度探索,从实现到应用详解
|
24天前
|
Linux C++ Windows
栈对象返回的问题 RVO / NRVO
具名返回值优化((Name)Return Value Optimization,(N)RVO)是一种优化机制,在函数返回对象时,通过减少临时对象的构造、复制构造及析构调用次数来降低开销。在C++中,通过直接在返回位置构造对象并利用隐藏参数传递地址,可避免不必要的复制操作。然而,Windows和Linux上的RVO与NRVO实现有所不同,且接收栈对象的方式也会影响优化效果。
|
26天前
crash —— 获取内核地址布局、页大小、以及栈布局
crash —— 获取内核地址布局、页大小、以及栈布局
|
26天前
|
存储 程序员 C语言
堆和栈之间有什么区别
【9月更文挑战第1天】堆和栈之间有什么区别
98 0
|
1月前
栈的几个经典应用,真的绝了
文章总结了栈的几个经典应用场景,包括使用两个栈来实现队列的功能以及利用栈进行对称匹配,并通过LeetCode上的题目示例展示了栈在实际问题中的应用。
栈的几个经典应用,真的绝了