C语言 ————栈

在 C++ 中,栈(Stack)是一种重要的数据结构,栈是一种特殊的线性表,它只能在一端进行插入和删除操作,这一端被称为栈顶(Top),另一端则称为栈底(Bottom)。栈遵循后进先出(Last In First Out,LIFO)的原则,就像一摞盘子,最后放上去的盘子会最先被取下来。

栈的基础

应用场景:
  • 函数调用栈:在 C++ 程序中,当函数被调用时,系统会将函数的参数、局部变量等信息压入栈中,函数执行完毕后再将这些信息弹出栈。通过这种方式,实现了函数调用的嵌套和返回。
  • 表达式求值:在计算表达式时,常常利用栈来处理运算符的优先级和操作数。例如,对于中缀表达式3 + 4 * 2,可以将运算符和操作数分别压入栈中,根据运算符的优先级进行计算。
  • 括号匹配:在检查代码中的括号是否匹配时,可以使用栈。当遇到左括号时将其压入栈,遇到右括号时检查栈顶元素是否为对应的左括号,如果是则将左括号出栈,否则括号不匹配。

除了以上基本应用,c++可以使用头文件使用栈,基于此也衍生出了多种栈的功能。

相关操作
  • 入栈(Push):将元素添加到栈顶的操作。例如,在一个整数栈中,执行 push (5) 操作,就是将数字 5 添加到栈顶
  • 出栈(Pop):移除栈顶元素的操作。执行 pop () 操作后,栈顶元素被删除,栈的大小(size)减 1。
  • 获取栈顶元素(Top):可以通过 top () 函数获取栈顶元素的值,但并不删除该元素。
  • 判断栈是否为空(Empty):使用 empty () 函数来检查栈是否为空,如果栈中没有任何元素,返回 true(1),否则返回 false(0)。
  • 获取栈的大小(Size):通过 size () 函数可以获取栈中元素的数量(大小)。
数组模拟栈: 

数组模拟栈有很大局限性,必须提前确定栈的大小

#include
using namespace std;
int stack[10000], Top=-1;
void push(int data) {stack[++Top] = data;}
void pop() {if (Top == -1) {exit(-1);}else {--Top;}}
int top() {return stack[Top];}
bool empty() {if (Top == -1) {return true;}else {return false;}}
int size() {return Top+1;}
int main() {
    push(10);
    push(20);
    cout << size() << endl;
    cout << top() << endl;
    pop();
    cout << size() << endl;
    cout << top() << endl;
    return 0;
}
链表模拟栈:
#include
using namespace std;
struct node {
    int data;
    node *next;
};
struct node *creatnode(int data) {
    node *newnode = new node;
    newnode->data = data;
    newnode->next = NULL;
    return newnode;
}
void push(int data, node *&head) {
    node *newnode = creatnode(data);
    if (head == NULL) {
        head = newnode;
        return;}
    node *temp = head;
    while (temp->next != NULL) {temp = temp->next;}
    temp->next = newnode;
}
void pop(node *head) {
    if (head == NULL) {exit(-1);}
    node *temp = head;
    while (temp->next->next != NULL) {temp = temp->next;}
    delete temp->next;
    temp->next = NULL;
}
int top(node *head) {
    if (head == NULL) {exit(-2);}
    node *temp = head;
    while (temp->next != NULL) {temp = temp->next;}
    return temp->data;
}
bool empty(node *head) {if (head == NULL) {return true;}return false;}
int size(node *head) {
    if (head == NULL) {return 0;}
    int count = 1;
    node *temp = head;
    while (temp->next != NULL) {temp = temp->next;count++;}
    return count;
}
int main() {
    node *head = NULL;
    push(1, head);
    push(2, head);
    cout << top(head) << endl;
    cout << size(head) << endl;
    cout << empty(head) << endl;
    pop(head);
    cout << top(head) << endl;
    return 0;
}
栈(本尊):
#include 
#include 
using namespace std;// 使用标准命名空间
int main() {
    stack myStack; // 创建一个存储整数的栈
    myStack.push(10);// 入栈操作:向栈中添加元素
    myStack.push(20);
    myStack.push(30);
    cout << "栈的大小: " << myStack.size() << endl;
    if (!myStack.empty()) {cout << "栈顶元素: " << myStack.top() << endl;}
    myStack.pop();// 出栈操作:移除栈顶元素
    cout << "\n执行出栈操作后:" << endl;// 再次输出栈的状态
    cout << "栈的大小: " << myStack.size() << endl;
    if (!myStack.empty()) {cout << "栈顶元素: " << myStack.top() << endl;}
    // 持续出栈直到栈为空
    while (!myStack.empty()) {myStack.pop();}
    cout << "\n多次出栈后,栈是否为空: " << (myStack.empty() ? "是" : "否") << endl;
    return 0;
}
例题:

洛谷P1449,后缀表达式,对应栈的表达式求值应用

#include
#include
using namespace std;
int main() {
    char c[100];
    stack st;
    int n=0;
    fgets(c,100,stdin);
    for(int i=0;c[i]!='@';i++) {
        if(c[i]>='0' && c[i]<='9') {n=c[i]-'0'+n*10;continue;}
        else if(c[i]=='.') {st.push(n);n=0;continue;}
        n=st.top();
        st.pop();
        if(c[i]=='-'){n=st.top()-n;}
        else if(c[i]=='/'){n=st.top()/n;}
        else if(c[i]=='*'){n=st.top()*n;}
        else if(c[i]=='+'){n=st.top()+n;}
        st.pop();
        st.push(n);
        n=0;
    }
    cout<

单调栈

单调栈是一种特殊的栈结构,它的特点是栈内元素始终保持单调递增或者单调递减。在处理一些与数组元素的大小关系、位置关系相关的问题时,单调栈能发挥重要作用,其时间复杂度通常为

O(n) ,因为每个元素最多进栈和出栈一次。

分类:(从下至上的单调)
  • 单调递增栈:栈内元素从栈底到栈顶依次递增。当新元素入栈时,如果新元素小于栈顶元素,则不断弹出栈顶元素,直到满足新元素大于等于栈顶元素,再将新元素入栈。(栈顶最大
  • 单调递减栈:栈内元素从栈底到栈顶依次递减。当新元素入栈时,如果新元素大于栈顶元素,则不断弹出栈顶元素,直到满足新元素小于等于栈顶元素,再将新元素入栈。(栈顶最小
常见应用场景:
  • 寻找下一个更大元素:对于数组中的每个元素,找到它右边第一个比它大的元素。可以使用单调递减栈来解决,当新元素大于栈顶元素时,栈顶元素的下一个更大元素就是新元素。
  • 计算直方图中的最大矩形面积:给定一组非负整数表示直方图的高度,计算直方图中能够勾勒出的最大矩形面积。可以使用单调递增栈来解决,通过维护栈内元素的单调性,找到每个柱子左右两边第一个比它矮的柱子的位置,从而计算出以该柱子为高的矩形的最大面积。
  • 股票价格跨度问题:给定一个股票价格数组,对于每个价格,计算其价格跨度(即该价格之前连续小于等于它的价格的天数)。可以使用单调递减栈来解决,栈中存储的是元素的索引,通过比较栈顶元素对应的价格和当前价格,计算出价格跨度。
例: 寻找下一个更大元素:

洛谷P5788单调栈

简述:寻找一个右边第一个更大的数

  • 从左至右使用单调栈的方法:

技巧:使用单调栈,确切的说是单调递减栈(存放的是索引,或者是下标,用

a【stack.top()】,小的在上面top),如果这个数小,显然不符合,直接入栈(答案不是从左到右按顺序出的,找到哪个元素的答案就先记录下来,有的数甚至没有答案),遇到大于栈顶(a[stack.top()])的数就将其小于它的站内元素先出栈,而一个元素出栈的时候就是找到右边比他大的数的时候(此时记录答案)

#include
#include
using namespace std;
int main() {
    int n;
    stack s;
    cin>>n;
    int a[n],ans[n]={0};
    for(int i=0;i>a[i];}
    for(int i=0;i=a[i]) {s.push(i);i++;}
        else {
            ans[s.top()]=i+1;
            s.pop();
        }
    }
    for(int i=0;i
  • 从右至左的倒序方法:

从后往前遍历,保持底部最大,如果数小于栈顶top,就将索引入栈(入栈前的栈顶top是当前要入栈元素的答案,即比当前元素大的数),如果数大于栈顶top,将栈顶弹出,来维护单调递减。

#include
#include
using namespace std;
int main() {
    int n;
    stack s;
    cin>>n;
    int a[n+1],ans[n+1]={0};
    for(int i=1;i<=n;i++) {cin>>a[i];}
    for(int i=n;i>0;) {
        if(s.empty()) {s.push(i);i--;}
        else {
            if(a[s.top()]>a[i]) {
                ans[i]=s.top();
                s.push(i);
                i--;
            }
            else {
                s.pop();
            }
        }
    }
    for(int i=1;i<=n;i++) {cout<

寻找左边第一个更大的数直接将原数组颠倒就行了,哪边是左是人定的。

你可能感兴趣的:(c++,c++,开发语言,c语言,算法,数据结构)