当我们谈论栈时,我们指的是一种在计算机科学中常见的数据结构,它遵循“后进先出”(Last In First Out,LIFO)的原则。这意味着最后进入栈的元素会首先被移除。
栈的基本操作:
1. 压入(Push):在栈顶添加元素。
2. 弹出(Pop):移除栈顶元素。
3. 获取栈顶元素(Top):返回但不移除栈顶元素。
4. 判空(Empty):检查栈是否为空。
5. 获取栈大小(Size):返回栈中元素的数量。
应用场景:
函数调用和递归实现:当一个函数被调用时,其局部变量和返回地址被存储在栈中,函数执行完成后,栈顶元素被弹出,控制流返回到调用该函数的地方(快速排序非递归写法)。
括号匹配:栈可用于检查表达式中括号是否匹配。(20. 有效的括号 - 力扣(LeetCode))
栈的实现方式:
1. 数组:使用数组实现栈时,栈顶元素通常是数组的末尾,压入和弹出操作的时间复杂度为 O(1)。
2. 链表:使用链表实现栈时,栈顶元素通常是链表的头部,同样具有 O(1) 的时间复杂度。
总的来说,栈是一种非常有用的数据结构,能够在各种算法和应用中发挥重要作用,同时也是理解计算机底层原理和编程概念的重要基础之一。
#include<iostream>
#include<stdlib.h>
#include<cstdbool>
using namespace std;
typedef int Datatype;
class Stack
{
public:
Stack(int capacity = 4);
~Stack();
void Push(Datatype x);
void New_capacity();
void Pop();
void pPop();
bool Empty();
private:
Datatype* _data;
int _size;
int _capacity;
};
Stack::Stack(int capacity=4)
{
_data = (Datatype*)malloc(sizeof(Datatype) * capacity);
if (_data == nullptr)
{
perror("malloc");
exit(-1);
}
int _size = 0;
}
Stack::~Stack()
{
free(_data);
_data = nullptr;
_size = _capacity = 0;
}
我使用数组实现,所以我们需要判断栈数组是否已经存满,也就存在New_capacity()扩容
Push
void Stack::New_capacity()
{
_capacity *= 2;
Datatype* temp = (Datatype*)realloc(_data, sizeof(Datatype) * _capacity);//扩容,同时防止内存分配失败导致数据丢失
if (temp == nullptr)
{
perror("malloc");
exit(-1);
}
_data = temp;//更新指针指向的内存地址
}
void Stack::Push(Datatype x)
{
if (_size == _capacity)//判断是否栈数组已满
{
New_capacity();
}
_data[_size++] = x;
}
对于栈,其实就是顺序表的部分场景的使用,主要是理解数据结构栈的思想用以解决问题!
Pop与Top
void Stack::Pop()
{
assert(!Empty());
_size--;
}
Datatype Stack::pPop()
{
assert(!Empty());
return _data[_size - 1];
}
删除数据与取数据的时候我们都需要判断栈数组内是否还有数据,也就是判空
Empty
bool Stack::Empty()
{
return _size == 0;
}
代码见:study/data structure_c c++/stack/Project1 at main · zjsnh/study (github.com)