浙大数据结构ch2:链表,队列,堆栈

这篇博客探讨了数据结构中的栈和队列在不同场景下的应用,如模拟队列和堆栈,以及如何使用它们解决实际问题。文章通过C++代码展示了如何用栈实现中缀表达式的后缀转换,同时讲解了广义表的概念,包括其存储结构和操作。此外,还介绍了顺序和链式结构的栈和队列的实现,并提供了相关操作的示例代码。
摘要由CSDN通过智能技术生成

1051 Pop Sequence

#include <bits/stdc++.h>
using namespace std;
stack<int> s;
int n,m,k;
int tmp;
int main(){
    scanf("%d%d%d",&m,&n,&k);
    for (int i=0;i<k;i++){
        stack<int> s;
        int cnt=1;
        bool flag=false;
        for (int i=0;i<n;i++){
            scanf("%d",&tmp);
            if (!s.empty() && s.top()==tmp){
                //cout << "debug1" << endl;
                s.pop();
            }
            else if (s.size()<m){
                //cout << "debug2" << endl;
                while (cnt!=tmp && s.size()<m){
                    s.push(cnt);
                    cnt++;
                }
                //cout << s.size() << ' ' << tmp << endl;
                if (s.size()==m){
                    //没找到这个数字就满了
                    flag=true;
                }
                //cnt==tmp相等的时候不压入
                else cnt++;
            }
            else{
                //cout << "debug3" << endl;
                flag=true;
            }
        }
        if (!flag) printf("YES\n");
        else printf("NO\n");
    }
    
}

7-22 堆栈模拟队列,能模拟的队列容量 <= 两个堆栈容量之和,可以参考232.用栈实现队列中的图,主要想法是通过两个栈的倒换改变元素的顺序,而225. 用队列实现栈中可以通过先入队再出队的方法备份前面的元素猫狗收养问题是典型的队列应用

#include <stack>
#include <iostream>
using namespace std;

class myQ{
public:
    stack<int> sin;
    stack<int> sout;
    int inSize,outSize,inCap,outCap;
    //必须小的那个栈做输入栈,大的栈做输出栈,因为输入栈满了之后要倒入输出栈
    myQ(int max,int min):inCap(min),outCap(max),inSize(0),outSize(0){};
    void AddQ(int x){
        //输入的元素放入in,如果满了就看看能不能放到sout
        if (inSize<inCap){
            sin.push(x);
            inSize++;
        }
        else{
            //inSize==inCap
            if (!sout.empty()){ //这里不能用outCap==outSize判断
                cout << "ERROR:Full" << endl;
                return;
            }
            //倒入输入栈
            while (!sin.empty()){
                int x=sin.top();sin.pop();
                sout.push(x);
                outSize++;
            }
            sin.push(x);
            inSize=1;
        }
    }
    void DeleteQ(){
        int x;
        //输出输出栈的内容,如果没有的话就看看输入栈
        if (!sout.empty()){
            x=sout.top();sout.pop();
            outSize--;
        }
        else{
            if (sin.empty()){
                cout << "ERROR:Empty" << endl;
                return;
            }
            while (!sin.empty()){
                int x=sin.top();sin.pop();
                sout.push(x);
                outSize++;
            }
            inSize=0;
            x=sout.top();sout.pop();
            outSize--;
        }
        cout << x << endl;
    }
};

int main(){
    int n1,n2;
    myQ* q;
    cin >> n1 >> n2;
    if (n1>n2) q=new myQ(n1,n2);
    else q=new myQ(n2,n1);
    int x;
    char c;
    cin >> c;
    while (c!='T'){
        if (c=='A'){
            cin >> x;
            q->AddQ(x);
        }
        else if (c=='D') q->DeleteQ();
        //cout << "inSize=" << q->inSize << "outSize=" << q->outSize << endl;
        cin >> c;
    }
}

下面是中缀表达式转后缀表达式,后缀表达式求值直接用堆栈可解决,前缀表达式求值只需读入全部字符串,再倒着遍历字符,处理方法与后缀表达式求值类似。后缀表达式求值前缀表达式求值一定要熟练,视频在这中缀表达式求值可以先写出下面的转换,再利用堆栈计算转换后的后缀表达式

//数字的相对顺序不变,计算符号的相对顺序改变
//存储"等待中"的运算符号,将当前运算符号与"等待中"的最后一个运算符号比较
//如果当前运算符优先级低,那么栈内优先级高的就可以输出
//左括号在外面优先级最高,在栈内优先级最低
//遇到右括号,输出到左括号结束
//同一优先级堆栈内的先输出

/*
测试点

序号    输入                     输出                                   说明
0    2+3*(7-4)+8/4            2 3 7 4 - * + 8 4 / +            正常测试6种运算符
1    ((2+3)*4-(8+2))/5        2 3 + 4 * 8 2 + - 5 /            嵌套括号
2    1314+25.5*12             1314 25.5 12 * +                 运算数超过1位整数且有非整数出现
3    -2*(+3)                  -2 3 *                           运算数前有正负号
4    123                      123                              只有一个数字

*/

#include <stack>
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

int main(){
    //m是计算符的优先级,( 放入堆栈内优先级最低
    map<char,int> m={{'(',0},{')',0},{'+',1},{'-',1},{'*',2},{'/',2}};
    string str;
    cin >> str;
    stack<char> s;
    string num; //存储数字
    vector<string> res; //存储输出结果
    for (int i=0,len=str.size();i<len;i++){
        //下面第一个if是得到数字,这个是细节最多的地方
        if(isdigit(str[i]) || (((i==0 || str[i-1]=='(')) && (m[str[i]]==1))){
            //单纯数字                 //({正负号}{数字})的情况,即序号3的输入
            if(str[i]!='+') num={str[i]};
            while(isdigit(str[i+1]) || str[i+1]=='.'){
                num+=str[i+1];
                i++;
            }
            res.push_back(num);
            num="";
        }
        else{
            if (str[i]=='(') s.push(str[i]);
            else if (str[i]==')'){
                while (!s.empty() && s.top()!='('){
                    res.push_back({s.top()});s.pop();
                }
                s.pop();
            }
			else{
				//						注意这里是<=
				while(!s.empty()&&m[str[i]]<=m[s.top()]){//这里需要注意,如果是空栈,直接压栈即可,如果栈顶元素的优先级大于等于s【i】,需要先将栈顶元素放入v中,再进行压栈,这里的循环是重点,需要掌握。
					res.push_back({s.top()});s.pop();
				}
				s.push(str[i]);
            }
        }
    }
    while (!s.empty()){
        res.push_back({s.top()});s.pop();
    }
    cout << res[0];
    for (int i=1,len=res.size();i<len;i++) cout << ' ' << res[i];
    return 0;
}

#include <iostream>
#define MAXSIZE 10000
using namespace std;

template<typename T>
class LNode{ //顺序实现
    public:
        T data[MAXSIZE];
        int last; //最后一个元素的下标
    LNode():last(-1){}; //这里必须是-1,添加一个元素后是0,满足insert
    int find(T x){
        int i=0;
        while (i<=last && data[i]!=x) x++;
        if (i>last) return -1;
        return i;
    }
    void insert(int i,T x){
        int j;
        // 注意下面的两个判定
        if (last==MAXSIZE-1){
            cout << "表满" << endl;
            return;
        }
        if (i<0 || i>last+1){ //可以插到last+1,不能插到last+2
            cout << "位置不合法" << endl;
            return;
        }
        for (j=last;j>=i;j--) data[j+1]=data[j]; //注意遍历顺序及等号的有无
        data[i]=x;
        last++;
    }
    void Delete(int i){
        if (i<0 || i>last){
            cout << "元素不存在" << endl;
            return;
        }
        for (int j=i;j<last;j++){ //注意遍历顺序
            data[j]=data[j+1];
        }
        last--;

    }
};
template<typename T>
class lNode{ //链表实现
    public:
    T data;
    lNode* next;
    lNode(T x):data(x),next(nullptr){};
    int length(){
        int i=1;
        lNode* head=this;
        while (head->next){
            i++;
            head=head->next;
        }
        return i;
    }
    lNode* insert(int i,T x){
        lNode* s=new lNode(x);
        if (i==0){
            //要分头部和非头部
            s->next=this;
            return s;
        }
        lNode* p=findKth(i-1); //△插入删除都是找i-1个元素△
        if (!p){
            cout << "参数错误" << endl;
            return this;
        }
        s->next=p->next;
        p->next=s;
        return this;
    }
    lNode* findX(T x){
        lNode* head=this;
        while (head && head->data!=x){
            head=head->next;
        }
        return head; //不需要if判断,空了自然就返回null
    }
    lNode* findKth(int k){
        int i=0;
        lNode* head=this;
        while (head && i<k){
            head=head->next;
            i++;
        }
        if (i==k) return head;
        return nullptr;
    }
    lNode* deleteKth(int k){
        if (k==0){
            if (this==nullptr){
                cout << "头节点为空" << endl;
                return nullptr;
            }
            else{
                lNode* head=this;
                lNode* s=head->next;
                delete head;
                return s;
            }
        }
        lNode* p=findKth(k-1);
        if (!p){
            cout << k-1 << " 节点不存在" << endl;
            return this;
        }
        if (!p->next){
            cout << k << " 节点不存在" << endl;
            return this;
        }
        lNode* s=p->next; //要删除的是p->next
        p->next=s->next;
        delete s;
        return this;
    }


};
template<typename T>
class GNode{ //广义表,表中的元素是另一个广义表或单元素,可以用union
    int tag; //0表示单元素
    union{
        T data;
        GNode* subList;
    }UReign;
    GNode* next;
};

template<typename T>
class Stack{
    //后入先出,数组实现
    T data[MAXSIZE];
    int top;
    Stack():top(-1){};
    void push(T x){
        if (top==MAXSIZE-1){
            cout << "栈满" << endl;
            return;
        }
        data[++top]=x;
    }
    T pop(){
        if (top==-1){
            cout << "栈空" << endl;
            return nullptr;
        }
        return data[top--];
    }


};

template<typename T>
class DStack{
    //一个数组实现两个堆栈
    T data[MAXSIZE];
    int top1;
    int top2;
    DStack():top1(-1),top2(MAXSIZE){};
    void push(T x,int tag){
        //tag是放哪个堆
        if (top2-top1==1){
            //比如两个指针挨在一起放不下
            cout << "栈满" << endl;
            return;
        }
        if (tag==1) data[++top1]=x;
        else data[--top2]=x;
    }
    T pop(int tag){
        if (tag==1){
            if (top1==-1){
                cout << "栈空" << endl;
                return nullptr;
            }
            else return data[top1--];
        }
        else{
            if (top2==MAXSIZE){
                cout << "栈空" << endl;
                return nullptr;
            }
            else return data[top2++];
        }
    }
};

template<typename T>
class SNode{
    //△链表实现堆栈,top必须是头节点△
    T data;
    SNode* next;
    SNode():next(nullptr){}; //头节点没有信息,dummy节点
    SNode(int x):data(x),next(nullptr){};
    bool isEmpty(){
        return next==nullptr;
    }
    void push(T x){
        SNode* s=new SNode(x);
        s->next=this->next;
        this->next=s;
    }
    T pop(){
        if (this->next==nullptr){
            cout << "栈空" << endl;
            return nullptr;
        }
        else{
            SNode* s=this->next;
            this->next=s->next;
            T d=s->data;
            delete s;
            return d;
        }
    }
};

template<typename T>
class Queue{
    T data[MAXSIZE];
    int front,rear; //△front是第一个元素前一个索引,rear是最后一个索引△
    //顺环队列rear和front相等时无法判断队列是空还是满
    //不放满队列可以解决
    Queue():front(0),rear(0){};
    void add(T x){  //△下一个放的位置是(rear+1)%MAXSIZE△
        if ((rear+1)%MAXSIZE==front){
            cout << "队列满" << endl;
            return;
        }
        rear=(rear+1)%MAXSIZE;
        data[rear]=x;
    }
    T DeleteX(){
        if (front==rear){
            cout << "队列空" << endl;
            return nullptr;
        }
        front=(front+1)%MAXSIZE;
        return data[front];
    }
};
template<typename T>
class node{ //链表节点
    T data;
    node* next;
    node(T x):data(x),next(nullptr){};
};
template<typename T>
class QNode{
    //链表实现queue
    //front做删除操作,rear做删除操作,链表头节点删掉之后找不到下一个,因此不能做front
    //只能头节点做front,尾结点做rear
    //△实现插入删除注意判断队列是否为空,很重要△
    node<T>* rear;
    node<T>* front;
    QNode():rear(nullptr),front(nullptr){};
    bool isEmpty(){
        return front==nullptr;
    }

    void add(T x){
        node<T>* s=new node<T>(x);
        if (isEmpty()){
            rear=front=s;
            return;
        }
        else{
            rear->next=s;
            rear=s;
        }
        return;
    }
    T Delete(){
        if (isEmpty()){
            cout << "队列空" << endl;
            return nullptr;
        }
        node<T>* s=front;
        if (front==rear){
            //队列只有一个元素
            front=nullptr;
            rear=nullptr;
        }
        else front=s->next;
        T d=s->data;
        delete s;
        return d;
    }
};

int main(){

    //栈实现中缀表达式
    //https://www.bilibili.com/video/BV1JW411i731?p=20&spm_id_from=pageDriver&vd_source=6c26f427606a59575440e9bc6cec44af&t=192.9
    lNode<int>* l=new lNode<int>(0);
    //LNode<int>* l=new LNode<int>();
    cout << l->data << ' ' << l->length() << endl;
    l=l->insert(0,1);
    l=l->insert(0,2);
    cout << l->data << ' ' << l->length() << endl;
    //l->insert(0,1);
    //l->insert(0,2);
    l=l->insert(0,3);
    l=l->insert(0,4);
    l=l->insert(0,5);
    l=l->deleteKth(0);
    cout << l->data << ' ' << l->length() << endl;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_森罗万象

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值