栈的概念
在正式讲栈的概念前,先举个例子,栈其实就像弹夹,我们把子弹一个一个压进去,开枪的时候最后一个压进去的子弹第一个被打出来。
栈也有这样的特性:“FILO”(First In,Last Out),先进后出,后进先出。我们不难发现栈
⊂
\subset
⊂数组或链表,那么为什么我们还需要栈而不直接使用数组或链表呢?因为在某些情况下我们不想让别人用其他的除了我们限定的方法处理数据。当我们要处理的数据满足上面FILO特性而且只被允许在一端push或pop时,栈是个很好的选择。
栈的实现
栈的链表实现跟数组实现差不多,区别在于数组实现需要提前初始化数组的大小,而链表实现可以实现动态扩容。所以我只写了个数组实现,当然数组也可以动态扩容,当栈满了的时候,先建一个比如两倍大的数组,再把原本的所有数据一次性拷贝,最后把原本的内存释放。原本没有写动态扩容代码的想法,写到这觉得干脆再补充一下吧。代码实现放在最后了。
栈的应用
平衡符号
一般来说,括号什么都是要一一对应,有开有闭(左括号’(‘和右括号 ‘)‘要一一对应,不能是’(‘对应’]’,只有’(‘没有’)‘也是不对的),栈就可以用来判断符号是否平衡。实现很简单,检测到’(’, ‘)’, ‘{’, ‘}’, ‘[’, ‘]’ 就把它们入栈,检测到对应的就将它们出栈,不对应的就报错,如果最后栈不为空也报错。
调用函数
函数的调用类似于平衡符号,可以这样理解,调用函数类似于左括号,函数运行完的返回类似于右括号。每调用一个函数,就会将所需要储存的信息(专有名词为活动记录或栈帧)入栈,返回后,就将这些信息出栈。
栈的数组版代码实现
MyStack.h
//
// Created by Sky on 2021/3/14.
//
#ifndef DATA_STRUCTURE_PRACTICES_MYSTACK_H
#define DATA_STRUCTURE_PRACTICES_MYSTACK_H
#include <iostream>
using namespace std;
class MyStack{
public:
MyStack(int n);
bool isEmpty();
bool isFull();
bool push(int num);
bool pop();
int top();
~MyStack();
private:
void expand();
int* data;
int capacity;
int size;
};
#endif //DATA_STRUCTURE_PRACTICES_MYSTACK_H
MyStack.cpp
//
// Created by Sky on 2021/3/14.
//
#include "MyStack.h"
MyStack::MyStack(int n) {
int* temp = new int[n];
data = temp;
capacity = n;
size = 0;
cout << "Stack has been created" << endl;
}
MyStack::~MyStack() {
delete data;
cout << "Stack has been deleted" << endl;
}
bool MyStack::isFull() {
if(capacity == size){
expand();
return true;
}
return false;
}
bool MyStack::isEmpty() {
if(size == 0)
return true;
return false;
}
bool MyStack::push(int num) {
if (isFull())
return false;
data[size++] = num;
return true;
}
bool MyStack::pop() {
if(isEmpty())
return false;
--size;
return true;
}
int MyStack::top() {
if (isEmpty())
return -1;
// cout << data[size] << endl;
return data[size-1];
}
void MyStack::expand() {
int* temp = new int [2*capacity];
for (int i = 0; i < capacity; i++){
temp[i] = data[i];
}
delete data;
data = temp;
capacity *= 2;
}
main.cpp
#include <iostream>
#include "MyStack.h"
using namespace std;
int main() {
MyStack s(5);
cout << boolalpha << "Can we pop? " << s.pop() << endl; // 测试空的情况下能不能pop
cout << boolalpha << "Is stack empty? " << s.isEmpty() << endl;// 测试空的情况下的返回值
cout << s.top() << endl; // 测试空的情况下能不能返回栈顶
s.push(111); // 测试push
cout << boolalpha << "Is stack empty? " << s.isEmpty() << endl;// 测试非空的情况下的返回值
cout << s.top() << endl; // 测试非空的情况下能不能返回栈顶
cout << boolalpha << "Can we pop? " << s.pop() << endl; // 测试非空的情况下能不能pop
s.push(2);
s.push(3);
s.push(4);
s.push(5);
s.push(6);
cout << boolalpha << "Is stack full? " << s.isFull() << endl; // 测试是否满了,满了之后会返回真,同时自动扩容
cout << boolalpha << "Is stack full? " << s.isFull() << endl; // 测试扩容后是否还会满
cout << boolalpha << "Can we push? " << s.push(7) << endl; //测试满了还能不能push
return 0;
}