【数据结构】栈和队列
栈的实现
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
#define SElemType int
#define Status int
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef struct {
SElemType *base; // 在栈构造之前和销毁之后,值位null
SElemType *top; // 栈顶指针
int StackSize; // 当前已分配的存储空间,以元素为单位
} SqStack;
// 构造一个空栈
Status InitStack(SqStack &S) {
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base) { // S.base == NULL
return OVERFLOW; // 内存分配失败
}
S.top = S.base;
S.StackSize = STACK_INIT_SIZE;
return OK;
} // InitStack
// 判断栈是否为空
bool IsEmpty(SqStack S) {
return S.top == S.base;
} // IsEmpty
// 元素入栈
Status Push(SqStack &S, SElemType e) {
if (S.top - S.base >= S.StackSize) {
S.base = (SElemType *)realloc(S.base, (S.StackSize + STACKINCREMENT) * sizeof(SElemType)); // 增加分配的空间
if (!S.base) {
return OVERFLOW; // 存储分配失败
}
S.top = S.base + S.StackSize;
S.StackSize += STACKINCREMENT;
}
*S.top = e;
S.top++;
return OK;
} // Push
// 元素出栈
Status Pop(SqStack &S, SElemType &e) {
if (IsEmpty(S)) { // 判断栈是否为空
return ERROR;
}
S.top--;
e = *S.top;
return OK;
} // Pop
// 获取栈顶元素
Status GetTop(SqStack S, SElemType &e) {
if (IsEmpty(S)) { // 判断栈是否为空
return ERROR;
}
e = *(S.top - 1);
return OK;
} // GetTop
队列的实现
#include <iostream>
using namespace std;
#define QElemType int
#define Status int
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXQSIZE 100 // 队列最大长度
typedef struct {
QElemType *base; // 分配存储空间
int front; // 头指针
int rear; // 尾指针
} SqQueue;
// 初始化循环队列
Status InitQueue(SqQueue &Q) {
Q.base = (QElemType*)malloc(MAXQSIZE * sizeof(QElemType));
if (!Q.base) {
return OVERFLOW;
}
Q.front = Q.rear = 0;
return OK;
} // InitQueue
// 求队列长度
int QueueLength(SqQueue Q) {
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
} // QueueLength
// 入队列
Status EnQueue(SqQueue &Q, QElemType e) {
if ((Q.rear + 1) % MAXQSIZE == Q.front) {
return ERROR; // 队列已经满了
}
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
return OK;
} // EnQueue
// 出队列
Status DeQueue(SqQueue &Q, QElemType &e) {
if (Q.front == Q.rear) {
return ERROR; // 队列已经满了
}
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return OK;
} // DeQueue
习题
堆栈
Problem A 有趣的括号
思路
逐个读取字符。若为左括号,则将其压入栈;若为右括号,判断栈顶元素是否为该右括号对应的左括号,若是则弹出栈顶元素,若不是则直接返回False。在最后判断栈是否为空,若为空则返回true,否则返回false。
代码
#include <iostream>
using namespace std;
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
#define SElemType char
#define Status int
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef struct {
SElemType *base; // 在栈构造之前和销毁之后,值位null
SElemType *top; // 栈顶指针
int StackSize; // 当前已分配的存储空间,以元素为单位
} SqStack;
// 构造一个空栈
Status InitStack(SqStack &S) {
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base) { // S.base == NULL
return OVERFLOW; // 内存分配失败
}
S.top = S.base;
S.StackSize = STACK_INIT_SIZE;
return OK;
} // InitStack
// 判断栈是否为空
bool IsEmpty(SqStack S) {
return S.top == S.base;
} // IsEmpty
// 元素入栈
Status Push(SqStack &S, SElemType e) {
if (S.top - S.base >= S.StackSize) {
S.base = (SElemType *)realloc(S.base, (S.StackSize + STACKINCREMENT) * sizeof(SElemType)); // 增加分配的空间
if (!S.base) {
return OVERFLOW; // 存储分配失败
}
S.top = S.base + S.StackSize;
S.StackSize += STACKINCREMENT;
}
*S.top = e;
S.top++;
return OK;
} // Push
// 元素出栈
Status Pop(SqStack &S, SElemType &e) {
if (IsEmpty(S)) { // 判断栈是否为空
return ERROR;
}
S.top--;
e = *S.top;
return OK;
} // Pop
// 获取栈顶元素
Status GetTop(SqStack S, SElemType &e) {
if (IsEmpty(S)) { // 判断栈是否为空
return ERROR;
}
e = *(S.top - 1);
return OK;
} // GetTop
// 判断是否为左括号
bool isLeftBracket(SElemType bracket) {
return (bracket == '(' || bracket == '[' || bracket == '{');
} // isLeftBracket
// 左括号转换为右括号
SElemType Reverse(SElemType &e) {
if (e == '(') {
return ')';
} else if (e == '[') {
return ']';
} else if (e == '{') {
return '}';
}
} // Reverse
SElemType bracket[100]; // 定义全局变量
int main() {
SqStack S;
InitStack(S);
int index = 0;
while (cin >> bracket[index]) {
if (bracket[index] == '\n') {
break;
}
++index;
}
for (int i = 0; i < index; ++i) {
if (isLeftBracket(bracket[i])) {
Push(S, bracket[i]);
} else {
if (IsEmpty(S)) {
cout << "False";
return 0;
} else {
SElemType elem;
GetTop(S, elem);
if (bracket[i] == Reverse(elem)) {
Pop(S, elem);
}
}
}
}
if (IsEmpty(S)) {
cout << "True";
} else {
cout << "False";
}
}
Problem B 进制转换
思路
首先输入对应的整数和进制类型,并把进制类型作为模数。每次对数进行取模,求得的数值压入栈。最后输出栈中的所有元素即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
#define SElemType char
#define Status int
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef struct {
SElemType *base; // 在栈构造之前和销毁之后,值位null
SElemType *top; // 栈顶指针
int StackSize; // 当前已分配的存储空间,以元素为单位
} SqStack;
// 构造一个空栈
Status InitStack(SqStack &S) {
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base) { // S.base == NULL
return OVERFLOW; // 内存分配失败
}
S.top = S.base;
S.StackSize = STACK_INIT_SIZE;
return OK;
} // InitStack
// 判断栈是否为空
bool IsEmpty(SqStack S) {
return S.top == S.base;
} // IsEmpty
// 元素入栈
Status Push(SqStack &S, SElemType e) {
if (S.top - S.base >= S.StackSize) {
S.base = (SElemType *)realloc(S.base, (S.StackSize + STACKINCREMENT) * sizeof(SElemType)); // 增加分配的空间
if (!S.base) {
return OVERFLOW; // 存储分配失败
}
S.top = S.base + S.StackSize;
S.StackSize += STACKINCREMENT;
}
*S.top = e;
S.top++;
return OK;
} // Push
// 元素出栈
Status Pop(SqStack &S, SElemType &e) {
if (IsEmpty(S)) { // 判断栈是否为空
return ERROR;
}
S.top--;
e = *S.top;
return OK;
} // Pop
// 获取栈顶元素
Status GetTop(SqStack S, SElemType &e) {
if (IsEmpty(S)) { // 判断栈是否为空
return ERROR;
}
e = *(S.top - 1);
return OK;
} // GetTop
int main() {
int num, conversion, mod;
cin >> num >> conversion;
SqStack S;
InitStack(S);
while (num) {
mod = num % conversion;
if (mod < 10) {
Push(S, mod + '0');
} else {
Push(S, (mod - 10) + 'A');
}
num = num / conversion;
}
while (!IsEmpty(S)) {
SElemType e;
Pop(S, e);
cout << e;
}
}
Problem C 表达式求值
思路
此题需要使用两个栈:操作数栈和操作符栈。对每个操作符设定一个优先级并进行比较,即可对操作数栈中的元素进行运算。最终操作数栈的栈顶元素即为表达式的值。
代码
#include <iostream>
#include <malloc.h>
#include <string>
using namespace std;
#define init_size 1
#define create_size 200
typedef struct Numstack {
int *top, *base;
int stacksize;
} numstack;
typedef struct Chstack {
char *top, *base;
int stacksize;
} chstack;
numstack num;
chstack ch;
string s;
bool isdigit(char c) {
if (c >= '0' && c <= '9') {
return true;
} else {
return false;
}
}
int pow(int a, int b) {
int ans = 1;
for (int i = 0; i < b; ++i) {
ans *= a;
}
return ans;
}
void init_stack(numstack &s) {
s.base = (int *)malloc(init_size * sizeof(int));
s.top = s.base;
s.stacksize = init_size;
}
void init_stack(chstack &s) {
s.base = (char *)malloc(init_size * sizeof(char));
s.top = s.base;
s.stacksize = init_size;
}
int top(numstack s) {
return *(s.top - 1);
}
char top(chstack s) {
return *(s.top - 1);
}
void push(numstack &s, int e) {
if (s.top >= s.base + s.stacksize) {
s.base = (int *)realloc(s.base, s.stacksize + create_size * sizeof(int));
s.top = s.base + s.stacksize;
s.stacksize += create_size;
}
*s.top = e;
s.top++;
}
void push(chstack &s, char e) {
if (s.top >= s.base + s.stacksize) {
s.base = (char *)realloc(s.base, s.stacksize + create_size * sizeof(char));
s.top = s.base + s.stacksize;
s.stacksize += create_size;
}
*s.top = e;
s.top++;
}
void pop(numstack &s) {
s.top--;
}
void pop(chstack &s) {
s.top--;
}
bool empty(chstack s) {
if (s.top == s.base) {
return true;
} else {
return false;
}
}
int size(numstack s) {
return (s.top - s.base) / sizeof(int *);
}
void calculate() {
int a = top(num);
pop(num);
int b = top(num);
pop(num);
char c = top(ch);
pop(ch);
switch (c) {
case '*':
push(num, b * a);
break;
case '/':
push(num, b / a);
break;
case '-':
push(num, b - a);
break;
case '+':
push(num, b + a);
break;
default:
push(num, pow(b, a));
break;
}
}
int check(char c) {
switch (c) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
default:
return 4;
}
}
int main() {
cin >> s;
for (int i = 0; i < s.length();) {
if (isdigit(s[i])) {
int mid = 0;
while (isdigit(s[i])) {
mid = mid * 10 + s[i++] - '0';
}
push(num, mid);
} else {
if (s[i] == '(') {
push(ch, s[i]);
} else if (s[i] == ')') {
while (top(ch) != '(') {
calculate();
}
pop(ch);
} else {
if (empty(ch) || check(s[i]) > check(top(ch))) {
push(ch, s[i]);
} else {
while (check(s[i]) <= check(top(ch))) {
if (top(ch) == '(') {
break;
}
calculate();
if (empty(ch)) {
break;
}
}
push(ch, s[i]);
}
}
++i;
}
}
while (size(num) != 1 && !empty(ch)) {
calculate();
}
cout << top(num);
}
队列
Problem A 银行业务队列简单模拟
思路
本题要使用两个队列,分别为A和B。根据”A窗口处理速度是B窗口的2倍“,可以在一次处理中弹出两个A队列元素和一个B队列元素。最后若有剩余则全部弹出即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define QElemType int
#define Status int
#define SElemType int
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
vector<int> out;
int num;
typedef struct QNode { // 定义结点
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front; // 队头指针
QueuePtr rear; // 队尾指针
} LinkQueue;
// 初始化一个空队列
Status InitQueue(LinkQueue &Q) {
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
if (!Q.front) {
return OVERFLOW;
}
Q.front->next = nullptr;
} // InitQueue
// 销毁队列
Status DestroyQueue(LinkQueue &Q) {
while (Q.front) {
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
return OK;
} // DestroyQueue
// 入队列
Status EnQueue(LinkQueue &Q, QElemType e) {
QNode *p;
p = (QueuePtr)malloc(sizeof(QNode));
if (!p) {
return OVERFLOW; // 存储分配失败
}
p->data = e;
p->next = nullptr;
Q.rear->next = p;
Q.rear = p;
return OK;
} // EnQueue
// 出队列
QElemType DeQueue(LinkQueue &Q) {
if (Q.front == Q.rear) {
return ERROR;
}
QNode *p;
p = Q.front->next;
QElemType e = p->data;
Q.front->next = p->next;
if (Q.rear == p) {
Q.rear = Q.front;
}
free(p);
return e;
} // Dequeue
// 判断是否为奇数
bool isOdd(int n) {
return (n % 2 != 0);
}
void OutAll(LinkQueue &La, LinkQueue &Lb, int la, int lb) {
if (la > 2 * lb) {
int c = 0;
for (int i = 1; i <= lb; ++i) {
out.push_back(DeQueue(La));
out.push_back(DeQueue(La));
out.push_back(DeQueue(Lb));
c += 3;
}
for (int i = 1; i <= num - c; ++i) {
out.push_back(DeQueue(La));
}
} else if (la == 2 * lb) {
for (int i = 1; i <= lb; ++i) {
out.push_back(DeQueue(La));
out.push_back(DeQueue(La));
out.push_back(DeQueue(Lb));
}
} else {
int c = 0;
for (int i = 1; i <= la / 2; ++i) {
out.push_back(DeQueue(La));
out.push_back(DeQueue(La));
out.push_back(DeQueue(Lb));
c += 3;
}
if (la % 2 != 0) {
out.push_back(DeQueue(La));
c++;
}
for (int i = 1; i <= num - c; ++i) {
out.push_back(DeQueue(Lb));
}
}
}
int main() {
while (out.size()) {
out.pop_back();
}
LinkQueue A, B;
InitQueue(A);
InitQueue(B);
int la = 0, lb;
cin >> num;
for (int i = 1; i <= num; ++i) {
int m;
cin >> m;
if (isOdd(m)) {
EnQueue(A, m);
la++;
} else {
EnQueue(B, m);
}
}
lb = num - la;
OutAll(A, B, la, lb);
for (int i = 0; i < out.size(); i++) {
if (i == out.size() - 1) {
cout << out[i];
} else {
cout << out[i] << " ";
}
}
}
Problem B 堆栈模拟队列
思路
本题需要使用两个堆栈,分别为S1和S2。取大小最大的栈为S1,较小的为S2。注意S1不能压满元素,而至多能装min(S1,S2)个元素。当S1满时把元素装到S2中,然后再弹出,即可模拟队列实现先进先出的特性。如图所示。
代码
#include <bits/stdc++.h>
using namespace std;
#define SElemType int
#define Status int
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef struct {
SElemType *base; // 在栈构造之前和销毁之后,值位null
SElemType *top; // 栈顶指针
int StackSize; // 当前已分配的存储空间,以元素为单位
} SqStack;
SqStack S1, S2;
// 构造一个空栈
Status InitStack(SqStack &S, int size) {
S.base = (SElemType *)malloc(size * sizeof(SElemType));
S.top = S.base;
S.StackSize = size;
return OK;
} // InitStack
// 判断栈是否为空
bool IsEmpty(SqStack S) {
return S.top == S.base;
} // IsEmpty
// 判断栈是否为满
bool IsFull(SqStack S) {
return (S.top >= S.base + S.StackSize);
}
// 元素入栈
Status Push(SqStack &S, SElemType e) {
*S.top = e;
S.top++;
return OK;
} // Push
// 元素出栈
SElemType Pop(SqStack &S) {
S.top--;
return *S.top;
} // Pop
// 获取栈顶元素
SElemType GetTop(SqStack S) {
SElemType e;
e = *(S.top - 1);
return e;
} // GetTop
// 转换
void transfer() {
while (!IsEmpty(S1)) {
Push(S2, Pop(S1));
}
} // transfer
// 队尾添加元素
void AddQ(SElemType e) {
if (!IsFull(S1)) {
Push(S1, e);
} else {
if (IsEmpty(S2)) {
transfer();
Push(S1, e);
} else {
cout << "ERROR:Full" << endl;
}
}
// if (IsFull(S1)) {
// if (!IsEmpty(S2)) {
// cout << "ERROR:Full" << endl;
// } else {
// transfer();
// Push(S1, e);
// }
// } else {
// Push(S1, e);
// }
}
// 队首弹出元素
void DeleteQ() {
if (IsEmpty(S2)) {
transfer();
if (IsEmpty(S2)) {
cout << "ERROR:Empty" << endl;
} else {
cout << Pop(S2) << endl;
}
} else {
cout << Pop(S2) << endl;
}
}
int main() {
int size1, size2;
cin >> size1 >> size2;
if (size1 > size2) {
swap(size1, size2);
}
InitStack(S1, size1);
InitStack(S2, size2);
char c;
int num;
while (cin >> c) {
if (c == 'T') {
break;
}
if (c == 'A') {
cin >> num;
AddQ(num);
} else {
DeleteQ();
}
}
return 0;
}