栈和队列详解(一)

简介: 栈和队列详解

1.栈


1.1栈的概念和结构


栈:特殊的线性表,只允许在固定的一端进行插入和删除数据。

进行数据插入和删除的一端称作栈顶,另一端称作栈底。


压栈:栈的插入操作称作压栈,压入栈的数据在栈顶

出栈:栈的删除操作称作出栈,出栈的数据也在栈顶


栈中数据遵守后进先出原则


压栈


713fe983c94af55a0d35430d4a5ad63b_a0b8063a74be41bf93dc604f7c0e1c68.png


出栈


a74eba794f1c02485551549cca94ebe4_768a5ade23c34d5bb3a26bb388258999.png


1.2栈的实现


栈的实现有两个选择数组,链表

二者相比,数组实现栈更好些,根据栈的特点,在尾部插入数据的情况下,数组更方便。


数组实现栈


b9a3f996e0a01e0f3a2ec5d85db119fa_23b0d77f84ef4d988af5974d4b8c24ed.png


链表实现栈


53e7f251e52c69a6a21de9daa3d4e62c_d21c04c07ab845c3aa78cf116b91a81d.png


这里采取数组的结构来实现栈


定义结构体和类型


typedef int SKdatatype;
typedef struct Stack
{
  SKdatatype* a;
  int top;//记录栈中元素的个数
  int capacity;//栈的容量
}SK;


初始化栈


//初始化栈
void SKinit(SK* ps);
void SKinit(SK* ps)
{
  assert(ps);
  ps->a = NULL;
  ps->top = ps->capacity = 0;
}

215401edab651a3240366ab1e07bfa46_094dedc5af51400fa7c4680c79b4790b.png


1faca118186230bf6144a5680dd2f762_85f478191c48442cab5833eca5726faf.png


销毁栈


//销毁栈
void SKdestory(SK* ps);
void SKdestory(SK* ps)
{
  assert(ps);
  ps->capacity = ps->top = 0;
  free(ps->a);
  ps->a = NULL;
}


数据压栈


//压栈
void SKpush(SK* ps, SKdatatype x);
void SKpush(SK* ps, SKdatatype x)
{
  assert(ps);
  //检查容量
  if (ps->capacity == ps->top)
  {
  int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
  SK* tmp = (SK*)realloc(ps->a, newcapacity * sizeof(SK));
  if (tmp == NULL)
  {
    perror("realloc fail");
    exit(-1);
  }
  ps->capacity = newcapacity;
  ps->a = tmp;
  }
  ps->a[ps->top] = x;
  ps->top++;
}


e30918bf896877eea3deef0790012692_c6c6b372eec745669386a7d39d7a74b5.png


压入两个数据进栈,监视如下


d7ce09e193342b552c0e6c42937b0228_00f0a1b3d91d4ba28f15006c1df5fa00.png


栈顶ps->top此时是2,说明栈中已经有两个数据。


数据出栈


//出栈
void SKpop(SK* ps);
void SKpop(SK* ps)
{
  assert(ps);
  assert(!SKempty(ps));
  ps->top--;
}


1a3d9db5e3c0b82365cbe1ed598e7307_37125278d9644adba8c691b47d78784c.png


数组中删除元素,不需要清除元素


将栈顶的数据出栈,监视如下


8e5d9191c7904cf34ef49825a36d7957_c1b1420606d24eaf9c5b679e71900801.png


栈顶ps->top此时是1,从上面可知,栈顶的数据已经出栈,栈中还有一个数据。


获得栈顶元素


//获得栈顶元素
SKdatatype SKtop(SK* ps);
SKdatatype SKtop(SK* ps)
{
  assert(ps);
  assert(!SKempty(ps));
  return ps->a[ps->top - 1];
}

7d3165fd13138d07a6528607c233a595_f82fe64949bd4d5a92ccb6495606de26.png


55293f9c954453edc109cc258af1bf15_a491e90c970e406cbf0023d2903cb859.png


检查栈是否为空


//检查是否是空栈
bool SKempty(SK* ps);
bool SKempty(SK* ps)
{
  assert(ps);
  return ps->top == 0;
}


计算栈中的数据个数


//计算栈中数据的个数
int SKsize(SK* ps);
int SKsize(SK* ps)
{
  assert(ps);
  return ps->top;
}


2.队列


2.1队列的概念及结构


队列:只允许在一端进行插入数据操作,另一端进行删除数据操作的特殊线性表

队列遵守先进先出原则

队尾:进行插入数据操作的一端

队头:进行删除数据操作的一端


a5bb3a5295dfb8197fa144a96fb05fab_b0216d3fa5f94e9e933511f1ef5a4342.png


目录
相关文章
|
7月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
246 1
|
5月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
118 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
10月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
500 77
|
9月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
228 11
|
9月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
10月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
411 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
10月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
236 7
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
1019 9
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
287 59

热门文章

最新文章

下一篇
oss云网关配置