915栈和队列部分参考代码,完整见PPT

顺序栈的定义

int stk[N], top = -1;

具体操作见PPT。


链栈

1. 节点定义

链栈的节点通常定义如下:

struct Node 
{
    int val;
    Node *next; 
    Node(int x) : val(x), next(NULL) {}
};

其中:

  • val 字段保存节点存储的数据
  • next 字段指向下一个节点,实现链式存储结构

链栈的基本操作需要使用链表的基本操作,如:

  • 初始化一个链栈常用头结点法,建立一个头结点,它的next指针初始化为NULL
  • 插入节点时,新建一个节点,将它的next指向原来栈顶节点,然后将栈顶指针指向新节点
  • 删除节点时,将栈顶指针指向原栈顶的next节点,释放原栈顶节点空间
  • 访问栈顶元素直接通过栈顶指针访问其val字段
  • 判断是否为空使用栈顶指针是否为NULL等

总之,通过next指针链接节点,实现链式存储,同时使用栈顶指针指向实际栈顶节点,就可以实现链栈的基本操作。

2. 初始化

链栈的初始化主要有两种方式:

  1. 初始化一个头结点
Node *init()    
{
    Node *dummy = new Node(-1);
    return dummy;
}

此时头结点仅代表栈的头,不存储实际数据,next指针初始化为NULL表示栈为空。

  1. 不使用头结点
Node *init() 
{
	return NULL;
}

此时为空栈直接返回NULL。

使用头结点的优点是:

  • 代码实现更简单,操作时直接使用 head指针代表栈 Head
  • 判断栈空时用head->next判断,避免每次都对NULL指针进行判断

不使用头结点可以减少一个额外的结点开销。

一般来说,使用头结点法是较为常见的链栈初始化实现方式。它简化了空栈的判断及后续的插入、删除等操作。

所以使用头结点法初始化一个链栈一般是最佳实践。

接下来的写法都是基于带头节点的链表来实现。

3. 判栈空
bool empty(Node *dummy)
{
    return dummy->next == NULL;
}
4. 进栈
void push(Node *dummy, int x)
{
    Node *node = new Node(x);
    node->next = dummy->next;
    dummy->next = node;
}
5. 出栈
// 为了使代码简洁突出原理,以下所有操作默认都是合法的
void pop(Node *dummy)
{
    dummy->next = dummy->next->next;
}
6. 读栈顶元素
int top(Node *dummy)
{
    return dummy->next->val;
}
完整代码
#include <iostream>

using namespace std;

struct Node
{
    int val;
    Node *next;
    Node(int x) : val(x), next(NULL) {}
};

// 链栈初始化
Node *init()    
{
    Node *dummy = new Node(-1);
    return dummy;
}

bool empty(Node *dummy)
{
    return dummy->next == NULL;
}

void push(Node *dummy, int x)
{
    Node *node = new Node(x);
    node->next = dummy->next;
    dummy->next = node;
}

// 为了使代码简洁突出原理,以下所有操作默认都是合法的
void pop(Node *dummy)
{
    dummy->next = dummy->next->next;
}

int top(Node *dummy)
{
    return dummy->next->val;
}

// 出栈链表剩余元素并输出
void print(Node *dummy)
{
    while (!empty(dummy))
    {
        cout << top(dummy) << ' ';
        pop(dummy);
    }
    cout << endl;
}

int main()  
{
    // 测试链栈各操作
    Node *dummy = init();
    push(dummy, 1);
    push(dummy, 2);
    push(dummy, 3);
    push(dummy, 4);
    
    printf("栈顶元素:%d\n", top(dummy));
    
    pop(dummy);
    
    printf("栈顶元素:%d\n", top(dummy));

    printf("栈是否为空:%d\n", empty(dummy));
    
    print(dummy);
    
    return 0;
}
栈顶元素:4
栈顶元素:3
栈是否为空:0
3 2 1 

在这里插入图片描述

在这里插入图片描述

class MyQueue {
private:
    stack<int> in, out;

    void in2out() {
        while (!in.empty()) {
            out.push(in.top());
            in.pop();
        }
    }
public:
    MyQueue() {}
    
    void push(int x) {
        in.push(x);
    }
    
    int pop() {
        if (out.empty()) {
            in2out();
        }
        int res = out.top();
        out.pop();
        return res;
    }
    
    int peek() {
        if (out.empty()) {
            in2out();
        }
        return out.top();
    }
    
    bool empty() {
        return out.empty() && in.empty();
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

在这里插入图片描述
在这里插入图片描述

class MyStack {
private:
    queue<int> q1, q2;

public:
    MyStack() {}
    
    void push(int x) {
        q2.push(x);
        while (!q1.empty()) {
            q2.push(q1.front());
            q1.pop();
        }
        swap(q1, q2);
    }
    
    int pop() {
        int res = q1.front();
        q1.pop();
        return res;
    }
    
    int top() {
        return q1.front();
    }
    
    bool empty() {
        return q1.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

在这里插入图片描述

class MyStack {
private:
    queue<int> q;

public:
    MyStack() {}
    
    void push(int x) {
        int n = q.size();
        q.push(x);
        while (n --) {
            q.push(q.front());
            q.pop();
        }
    }
    
    int pop() {
        int res = q.front();
        q.pop();
        return res;
    }
    
    int top() {
        return q.front();
    }
    
    bool empty() {
        return q.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

括号匹配

这个代码利用STL的stack来实现:

  • 遍历字符串,遇到开括号入栈
  • 遇到闭括号出栈与之比对
  • 最后判断栈是否为空,为空则括号匹配

通过给出具体代码,可以更清晰体现栈在括号匹配中的应用。

#include <iostream>
#include <stack>

using namespace std;

bool bracketMatch(string str)
{
    stack<char> s;
    for (char c: str)
    {
        if (c == '(' || c == '[' || c == '{') s.push(c);
        else
        {
            if (s.empty()) return false;
            char top = s.top();
            s.pop();
            if ((c==')' && top!='(') ||
               (c==']' && top!='[') ||
               (c=='}' && top!='{')) return false;
        }
    }
    return s.empty();
}

int main()
{
    string s1 = "((()))";
    string s2 = "([{{}])";

    if(bracketMatch(s1))
        cout << "s1 matched" << endl;
    else
        cout << "s1 not matched" << endl;

    if(bracketMatch(s2))
        cout << "s2 matched" << endl;
    else
        cout << "s2 not matched" << endl;

    return 0;
}

AcWing.3302中缀表达式求值:

2种解法:

  1. 直接求解

  2. 将中缀表达式转换为后缀表达式后进行解决

完整代码链接:https://www.acwing.com/activity/content/code/content/1466076/

冲击高分的同学需要掌握具体代码的实现

冲击平均分的同学只需理解算法

这里给出第二种解法的参考代码:

在这里插入图片描述

#include <iostream>
#include <stack>
#include <string>

using namespace std;

// 操作符优先级
int priority(char op) {
    if(op == '+' || op == '-')
        return 1;
    else if(op == '*' || op == '/') 
        return 2;
    else 
        return 0;
}

string infixToPostfix(string infix) {
    stack<char> st;
    string postfix;

    for(char c: infix) {
        if(c == ' ') continue; //跳过空格

        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { // c是字母
        // if(isdigit(c)) {  // c是具体的数字
            postfix += c; //操作数直接加入后缀表达式
        }
        else if(c == '(') {
            st.push(c); //左括号入栈
        }
        else if(c == ')') {
            while(!st.empty() && st.top() != '(') {
                postfix += st.top();
                st.pop();
            }
            if(!st.empty() && st.top() != '(') {
                return "Invalid Expression"; 
            }
            st.pop(); //弹出左括号
        }
        else { //运算符
            while(!st.empty() && priority(c) <= priority(st.top())) {
                postfix += st.top();
                st.pop();  
            }
            st.push(c);
        }
    }

    while(!st.empty()) {
        if(st.top() == '(') 
          return "Invalid Expression";
        postfix += st.top();
        st.pop();
    }

    return postfix;
}

int main() {
    string infix;
    cin >> infix;
    string postfix = infixToPostfix(infix);
    cout << postfix << endl;

    return 0;
}

输入:

(a+b)*(c+d)

输出:

ab+cd+*
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值