【PAT甲级复习】 专题复习八:基础数据结构专题

专题复习八(9.10):基础数据结构专题

1 栈

通常用数组来实现栈,使用栈顶指针TOP来控制,栈空时TOP为-1。

注意STL中的stack没有clear()函数,清空的最好办法是重新定义一个stack。

栈的应用:模拟递归,表达式计算,中缀表达式转后缀表达式

void clear(){
    TOP = -1;
}

int size(){
    return TOP + 1;
}

bool empty(){
    if(TOP == -1) return true;
    else return false;
}

void push(int x){
    st[++TOP] = x;
}

void pop(){
    TOP--;
}

int top(){
    return st[TOP];
}

中缀表达式转后缀表达式_qianyayun19921028的博客-CSDN博客_中缀表达式转后缀表达式

中缀表达式转后缀表达式:

  1. 设置一个操作符栈,用以临时存放操作符;设立一个队列或者数组,用以存放后缀表达式。

  2. 从左到右扫描中缀表达式,如果遇到操作数(注意:操作数可能不止一位,因此需要合并),就把操作数加入后缀表达式中。

  3. 如果遇到操作符,则将其优先级与栈顶操作符的优先级比较:

    • 如果遇到左括号,就压入操作符栈;如果遇到右括号,就把操作符栈里的元素不断弹出到后缀表达式直到碰到左括号,最后把左括号移除(不加入后缀表达式!

    • 如果op的优先级高于栈顶的,则压入操作符栈

    • 如果小于等于,则将操作符栈的操作符不断弹出到后缀表达式中,直到op的优先级高于栈顶的。

  4. 重复以上操作直到中缀表达式扫描完毕,如果操作符栈不为空,将他们依次弹出至后缀表达式中。

计算后缀表达式:

从左到右扫描后缀表达式,如果是操作数,就压入栈;如果是操作符,就连续弹出两个操作数(注意:后弹出的是第一操作数),然后进行操作符的操作,生成的新操作数压入栈中。反复直到后缀表达式扫描完毕,此时栈中只有一个数,就是最终的答案。

1.1 codeup 1918 简单计算器

C++ isalpha、isalnum、islower、isupper用法_帅比王的博客-CSDN博客

#include<iostream>
#include<cstdio>
#include<string>
#include<stack>
#include<queue>
#include<map>
using namespace std;
struct node{
    double num;
    char op;
    bool flag;
};
string str;
stack<node> s;
queue<node> q;
map<char, int> op;
void Change(){
    double num;
    node temp;
    for(int i=0; i<str.size(); ){
        if(isdigit(str[i])){
            temp.flag = 1;
            temp.num = str[i++] - '0';
            while(i<str.size() && isdigit(str[i])){
                temp.num = temp.num * 10 + str[i] - '0';
                i++;
            }
            q.push(temp);
        }
        else{
            temp.flag = 0;
            while(!s.empty() && op[str[i]] <= op[s.top().op]){
                q.push(s.top());
                s.pop();
            }
            temp.op = str[i];
            s.push(temp);
            i++;
        }
    }
    while(!s.empty()){
        q.push(s.top());
        s.pop();
    }
}

double Cal(){
    double temp1, temp2;
    node cur, temp;
    while(!q.empty()){
        cur = q.front();
        q.pop();
        if(cur.flag == 1) s.push(cur);
        else{
            temp2 = s.top().num;
            s.pop();
            temp1 = s.top().num;
            s.pop();
            temp.flag = 1;
            if(cur.op == '+') temp.num = temp1 + temp2;
            else if(cur.op == '-') temp.num = temp1 - temp2;
            else if(cur.op == '*') temp.num = temp1 * temp2;
            else temp.num = temp1 / temp2;
            s.push(temp);                
        }
    }
    return s.top().num;
}
int main(){
    op['+'] = op['-'] = 1;
    op['*'] = op['/'] = 2;
    while(getline(cin, str), str != "0"){
        for(auto it = str.begin(); it != str.end(); it++){
            if(*it == ' ') str.erase(it);
        }
        while(!s.empty()) s.pop();
        Change();
        printf("%.2f\n", Cal());
        return 0;
    }
}
1.2 A1051 Pop Sequence (25 分)

需要按照要求进行模拟。先把输入的序列接收进数组v。然后按顺序1~n把数字进栈,每进入一个数字,判断有没有超过最大范围,超过了就break。如果没超过,设current = 1,从数组的第一个数字开始,看看是否与栈顶元素相等,while相等就一直弹出栈,不相等就继续按顺序把数字压入栈~最后根据变量flag的bool值输出yes或者no

#include<bits/stdc++.h>
using namespace std;
int m, n, k;
int arr[1005];
int cur = 0;
int main(){
    cin >> m >> n >> k;
    for(int i=0; i<k; i++){
        cur = 0;
        for(int j=0; j<n; j++){
            scanf("%d", &arr[j]);
        }
        stack<int> s;
        for(int j=1; j<=n; j++){
            s.push(j);
            if(s.size() > m) break;
            while(!s.empty() && cur < n && s.top() == arr[cur]){
                s.pop();
                cur++;
            }            
        }
        if(cur == n) printf("YES\n");
        else printf("NO\n");
    }
}

2 队列

通常用数组来实现队列,需要一个队首指针front指向队首元素的前一个位置,一个队尾指针rear指向队尾元素。

STL中的queue没有clear()函数,清空的最好办法是重新定义一个queue。

队列的应用:模拟递归,表达式计算,中缀表达式转后缀表达式

void clear(){
    front = rear = -1;
}

int size(){
    return rear - front;
}

bool empty(){
    if(front == rear) return true;
    else return false;
}
void push(int x){
    q[++rear] = x;
}

void pop(){
    front++;
}

int get_front(){
    return q[front + 1];
}

int get_rear(){
    return q[rear];
}

例题A1056

3 链表

使用指针的链表:

struct Node{
    int data;
    Node* next;
};

Node* create(int Array[]){
    Node *p, *pre, *head;
    head = new Node;
    head->next = NULL;
    pre = head;
    for(int i=0; i<n; i++){
        p = new Node;
        p->data = Array[i];
        p->next = NULL;
        pre->next = p;
        pre = p;
    }
    return head;
}

int search(Node* head, int x){
    int cnt = 0;
    Node* p = head->next;
    while(p!=NULL){
        if(p->data == x) cnt++;
        p = p->next;
    }
    return cnt;
}

void insert(Node* head, int pos, int x){
    Node* p = head;
    for(int i=0; i<pos-1; i++){
        p = p->next;
    }
    Node* q = new Node;
    q.data = x;
    q->next = p->next;
    p->next = q;
}

void del(Node* head, int x){
    Node* p = head->next;
    Node* pre = head;
    while(p){
        if(p->data == x){
            pre->next = p->next;
            delete p;
            p = pre->next;
        }
        else{
            pre = p;
            p = p->next;
        }
    }
}

如果节点的地址是比较小的整数,比如说5位数的地址,就可以使用静态链表:A1052

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
struct Node{
    int key;
    int next;
    int onlist;
    int idx;
    Node(){
        onlist = 0;
        next = -1;
    }
}node[MAXN];

bool cmp(const Node &a, const Node &b){
    if(a.onlist != b.onlist) return a.onlist > b.onlist;
    else return a.key < b.key;
}

int n, head, cnt = 0;
int main(){
    int add, key, next;
    cin >> n >> head;
    for(int i=0; i<n; i++){
        scanf("%d %d %d",&add, &key, &next);
        node[add].key = key;
        node[add].next = next;
        node[add].idx = add;
    }
    while(head != -1){
        cnt++;
        node[head].onlist = 1;
        head = node[head].next;
    }
    sort(node, node+MAXN, cmp);
    if(cnt == 0) printf("0 -1\n");
    else{
    printf("%d %05d\n",cnt,node[0].idx);
    for(int i=0; i<cnt-1; i++){
        printf("%05d %d %05d\n",node[i].idx, node[i].key, node[i+1].idx);
    }
    printf("%05d %d -1\n",node[cnt-1].idx, node[cnt-1].key);        
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值