专题复习八(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博客_中缀表达式转后缀表达式
中缀表达式转后缀表达式:
-
设置一个操作符栈,用以临时存放操作符;设立一个队列或者数组,用以存放后缀表达式。
-
从左到右扫描中缀表达式,如果遇到操作数(注意:操作数可能不止一位,因此需要合并),就把操作数加入后缀表达式中。
-
如果遇到操作符,则将其优先级与栈顶操作符的优先级比较:
-
如果遇到左括号,就压入操作符栈;如果遇到右括号,就把操作符栈里的元素不断弹出到后缀表达式直到碰到左括号,最后把左括号移除(不加入后缀表达式!)
-
如果op的优先级高于栈顶的,则压入操作符栈
-
如果小于等于,则将操作符栈的操作符不断弹出到后缀表达式中,直到op的优先级高于栈顶的。
-
-
重复以上操作直到中缀表达式扫描完毕,如果操作符栈不为空,将他们依次弹出至后缀表达式中。
计算后缀表达式:
从左到右扫描后缀表达式,如果是操作数,就压入栈;如果是操作符,就连续弹出两个操作数(注意:后弹出的是第一操作数),然后进行操作符的操作,生成的新操作数压入栈中。反复直到后缀表达式扫描完毕,此时栈中只有一个数,就是最终的答案。
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);
}
}