堆栈数据结构(介绍与程序)

简介: 堆栈数据结构(介绍与程序)

堆栈是一种线性数据结构,它遵循执行操作的特定顺序。顺序可能是 LIFO(后进先出)或 FILO(先进后出)。

在栈中主要进行以下三个基本操作:

  • Push: 在堆栈中添加一个项目。如果堆栈已满,则称其为溢出条件。
  • Pop: 从堆栈中移除一个项目。这些项目以它们被推送的相反顺序弹出。如果堆栈为空,则称其为下溢条件。
  • Peek 或 Top: 返回堆栈的顶部元素。
  • isEmpty: 如果堆栈为空则返回true,否则返回false。

如何实际理解堆栈?

有许多现实生活中的堆栈示例。考虑一下在食堂里盘子叠在一起的简单例子。位于顶部的板是第一个被移除的板,即已放置在最底部位置的板在堆叠中保留的时间最长。所以,可以简单的看出遵循LIFO/FILO的顺序。

堆栈操作的时间复杂度:

push()、pop()、isEmpty() 和 peek() 都需要 O(1) 时间。我们不会在任何这些操作中运行任何循环。

堆栈的应用:

  • 符号的平衡
  • 中缀到后缀/前缀的转换
  • 许多地方的重做-撤消功能,如文本编辑器、WPS、Photoshop。
  • Web 浏览器中的前进和后退功能
  • 用于许多算法,如河内塔、树遍历、库存跨度问题、直方图问题。
  • 回溯是算法设计技术之一。回溯的一些例子是 Knight-Tour 问题、N-Queen 问题、在迷宫中找到自己的方式,以及所有这些问题中的类似游戏的国际象棋或跳棋问题,如果这种方式效率低下,我们会回到以前的问题状态并进入另一条路径。为了从当前状态返回,我们需要为此目的存储先前的状态,我们需要一个堆栈。
  • 在诸如拓扑排序和强连通分量之类的图算法中
  • 在内存管理中,任何现代计算机都使用堆栈作为运行目的的主要管理。在计算机系统中运行的每个程序都有自己的内存分配
  • 字符串反转也是堆栈的另一个应用。在这里,每个字符都被一个一个地插入到堆栈中。所以字符串的第一个字符在栈底,字符串的最后一个元素在栈顶。在堆栈上执行弹出操作后,我们得到一个相反顺序的字符串。

实现:

栈的实现有两种方式:

  • 使用数组
  • 使用链表

使用数组实现堆栈

c++

复制代码


#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
class Stack {
  int top;
public:
  int a[MAX]; 
  Stack() { top = -1; }
  bool push(int x);
  int pop();
  int peek();
  bool isEmpty();
};
bool Stack::push(int x)
{
  if (top >= (MAX - 1)) {
    cout << "Stack Overflow";
    return false;
  }
  else {
    a[++top] = x;
    cout << x << " 压入堆栈\n";
    return true;
  }
}
int Stack::pop()
{
  if (top < 0) {
    cout << "Stack Underflow";
    return 0;
  }
  else {
    int x = a[top--];
    return x;
  }
}
int Stack::peek()
{
  if (top < 0) {
    cout << "Stack is Empty";
    return 0;
  }
  else {
    int x = a[top];
    return x;
  }
}
bool Stack::isEmpty()
{
  return (top < 0);
}
int main()
{
  class Stack s;
  s.push(10);
  s.push(20);
  s.push(30);
  cout << s.pop() << " 从堆栈中弹出\n";
  cout<<"堆栈中存在的元素 : ";
  while(!s.isEmpty())
  {
    cout<<s.peek()<<" ";
    s.pop();
  }
  return 0;
}

输出 : 

10 压入堆栈
20 压入堆栈
30 压入堆栈
30 从堆栈中弹出
顶部元素是: 20
堆栈中存在的元素: 20 10  

优点: 易于实施。由于不涉及指针,因此节省了内存。

缺点: 它不是动态的。它不会根据运行时的需要增长和缩小。

使用链表实现堆栈:

#include <bits/stdc++.h>
using namespace std;
class StackNode {
public:
  int data;
  StackNode* next;
};
StackNode* newNode(int data)
{
  StackNode* stackNode = new StackNode();
  stackNode->data = data;
  stackNode->next = NULL;
  return stackNode;
}
int isEmpty(StackNode* root)
{
  return !root;
}
void push(StackNode** root, int data)
{
  StackNode* stackNode = newNode(data);
  stackNode->next = *root;
  *root = stackNode;
  cout << data << " pushed to stack\n";
}
int pop(StackNode** root)
{
  if (isEmpty(*root))
    return INT_MIN;
  StackNode* temp = *root;
  *root = (*root)->next;
  int popped = temp->data;
  free(temp);
  return popped;
}
int peek(StackNode* root)
{
  if (isEmpty(root))
    return INT_MIN;
  return root->data;
}
int main()
{
  StackNode* root = NULL;
  push(&root, 10);
  push(&root, 20);
  push(&root, 30);
  cout << pop(&root) << " popped from stack\n";
  cout << "Top element is " << peek(root) << endl;
  cout<<"Elements present in stack : ";
  while(!isEmpty(root))
  {
    cout<<peek(root)<<" ";
    pop(&root);
  }
  return 0;
}
目录
相关文章
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
283 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
44 1
|
11天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
127 75
|
11天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
34 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
11天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
35 9
|
11天前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
29 7
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
87 5
|
2月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
103 21
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
80 1
|
2月前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。

热门文章

最新文章