0%

Stack and Queue (Part 1)

Introduction

有了動態陣列之後,堆疊與佇列就可以被實作出來了。堆疊的基本概念是先進去的後出來,就像疊好的盤子。佇列則相反,先進去的會先出來,就像一群在排隊的人。

Stack

首先我們先來實作堆疊,你會發現,只要利用上次的push_back以及pop_back就可以很方便的做出堆疊的結構。

Template for your program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <vector>

struct Stack {
std::vector<int> values;
Stack& push(int value);
Stack& pop();
int top();
int size();
};

Stack& Stack::push(int value) {
// your code below

// your code above
return *this;
}

Stack& Stack::pop() {
// your code below

// your code above
return *this;
}

int Stack::top() {
// your code below

// your code above
return -1;
}

int Stack::size() {
return values.size();
}

const int PUSH{1};
const int POP{2};
const int TOP{3};

int main(void) {
int operation_num;
std::cin >> operation_num;

Stack st;
for (int i{0}; i < operation_num; ++i) {
int op, value;
std::cin >> op;
switch (op) {
case PUSH:
std::cin >> value;
st.push(value);
std::cout << st.size() << "\n";
break;
case POP:
st.pop();
break;
case TOP:
std::cout << st.top() << "\n";
break;
}
}
}

Usage of Stack

Evaluation of Arithmetic expression

https://zerojudge.tw/ShowProblem?problemid=a017

My answer written in C.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>

#define LEN 131072
#define OP 1
#define NUM 2

typedef struct token {
int64_t type, val;
} Token;

typedef struct stack {
Token *val;
int sz, base, top;
} Stack;

Stack NewStack(int sz);
void Rebase(Stack*);
void Push(Stack*, Token val);
void Pop(Stack*);
Token Top(Stack*);
void Delete(Stack*);

int64_t InfixToSufix(char [], Token []);
Token PostfixEval(Token [], int64_t);

int main(void) {
char infix[LEN] = {0};
Token postfix[LEN] = {0};
while(fgets(infix, LEN, stdin) != NULL) {
int64_t post_sz = InfixToSufix(infix, postfix);
printf("%lld\n", PostfixEval(postfix, post_sz).val);
}
}

// Create a new stack.
//
// Where sz means size
Stack NewStack(int sz) {
Stack new_stack;
new_stack.sz = sz;
new_stack.base = 1;
while(new_stack.base < new_stack.sz) {
new_stack.base <<= 1;
}
new_stack.val = (Token*) calloc(new_stack.base, sizeof(Token));
new_stack.top = -1;
return new_stack;
}

void Rebase(Stack* st) {
(st->base) <<= 1;
Token *new_val = (Token*) calloc(st->base, sizeof(Token));
for(int i = 0; i < st->sz; ++i) {
new_val[i] = st->val[i];
}
free(st->val);
st->val = new_val;
}

void Push(Stack *st, Token val) {
if(st->top >= st->sz - 1) {
st->sz++;
if(st->sz >= st->base) {
Rebase(st);
}
}
st->top++;
st->val[st->top] = val;
}

void Pop(Stack *st) {
assert(st->top >= 0);
st->top--;
}

Token Top(Stack *st) {
assert(st->top >= 0);
return st->val[st->top];
}

void Delete(Stack *st) {
free(st->val);
}

int64_t InfixToSufix(char infix[], Token postfix[]) {
Stack st = NewStack(16);
int64_t prior[128] = {0};
prior['+'] = prior['-'] = 1;
prior['*'] = prior['/'] = prior['%'] = 2;

int64_t inf_idx = 0, post_idx = 0;
while(infix[inf_idx] != '\0' && infix[inf_idx] != '\n') {
char token = infix[inf_idx];
inf_idx++;
if(token == ' ') {
continue;
} else if(isdigit(token)) {
int64_t tp = 0;
while(isdigit(token)) {
// printf("%c", token);
tp = (tp << 3) + (tp << 1) + (token - '0');
token = infix[inf_idx];
inf_idx++;
}
postfix[post_idx].type = NUM;
postfix[post_idx].val = tp;
post_idx++;
}
if(token == '\0' || token == '\n') break;
if(token == ' ') continue;
if(token == '(') {
Token tok = {OP, '('};
Push(&st, tok);
} else if(token == ')') {
while(st.top >= 0 && Top(&st).val != '('){
// printf("%c", (char)Top(&st).val);
postfix[post_idx++] = Top(&st);
Pop(&st);
}
Pop(&st);
} else {
while(st.top >= 0 && prior[Top(&st).val] >= prior[token]) {
// printf("%c", (char)Top(&st).val);
postfix[post_idx++] = Top(&st);
Pop(&st);
}
Token tok = {OP, token};
Push(&st, tok);
}
}
while(st.top >= 0) {
// printf("%c", (char)Top(&st).val);
postfix[post_idx++] = Top(&st);
Pop(&st);
}
// printf("=");
Delete(&st);
return post_idx;
}

int64_t Add(int64_t a, int64_t b) {
return a + b;
}

int64_t Sub(int64_t a, int64_t b) {
return a - b;
}

int64_t Mul(int64_t a, int64_t b) {
return a * b;
}

int64_t Div(int64_t a, int64_t b) {
return a / b;
}

int64_t Mod(int64_t a, int64_t b) {
return a % b;
}

Token PostfixEval(Token postfix[], int64_t post_sz) {
if(post_sz == 0) {
Token ret = {NUM, 0};
return ret;
}
Stack st = NewStack(16);
int64_t op_to_idx[128];
op_to_idx['+'] = 0;
op_to_idx['-'] = 1;
op_to_idx['*'] = 2;
op_to_idx['/'] = 3;
op_to_idx['%'] = 4;

int64_t (*op[5])(int64_t, int64_t) = {Add, Sub, Mul, Div, Mod};

for(int64_t post_idx = 0; post_idx < post_sz; ++post_idx) {
Token token = postfix[post_idx];
if(token.type == NUM) {
Push(&st, token);
} else {
Token a = Top(&st);
Pop(&st);
Token b = Top(&st);
Pop(&st);
Token push = {NUM, op[op_to_idx[token.val]](b.val, a.val)};
Push(&st, push);
}
}
Token ret = Top(&st);
Delete(&st);
return ret;
}

Home but not work

  1. 單調對列
  2. 模擬遞迴