栈的一些简单应用:
(1)数制转换:
- #include <stdio.h>
- #include "stack.h"
-
void conversion(int num, int base)
-
{
-
struct stack *s = init_stack();
-
while (num) {
-
push(s, num % base);
-
num /= base;
-
}
-
while(!stack_empty(s)) {
-
printf("%d", top(s));
-
pop(s);
-
}
-
destory_stack(s);
-
}
-
int main()
-
{
-
int num, base;
-
scanf("%d %d", &num, &base);
-
conversion(num, base);
-
return 0;
- }
(2)括号匹配检验:
- #include <stdio.h>
- #include "stack.h"
-
void match(char *str)
-
{
-
struct stack *s = init_stack();
-
char ch, *p;
-
bool flag = true;
-
for (p = str; *p != NULL && flag; p++) {
-
switch(*p) {
-
case '(':
-
case '[':
-
push(s, *p);
-
break;
-
case ')':
-
if ((ch = top(s)) == '(')
-
pop(s);
- else
-
flag = false;
-
break;
-
case ']':
-
if ((ch = top(s)) == '[')
-
pop(s);
- else
-
flag = false;
-
break;
-
default:
-
break;
-
}
-
}
-
if (stack_empty(s))
-
printf("brackets match right!/n");
- else
-
printf("brackets not match!/n");
-
destory_stack(s);
-
}
-
int main()
-
{
-
char s[20] = "[3+2)*5]*(2+5)";
-
match(s);
-
return 0;
- }
(3)行编辑:用户输入#表示前一个字符无效,输入一个@表示当前行中@前的字符都无效
- #include <stdio.h>
- #include "stack.h"
- #define MAXVAL 100
-
void lineedit(int *count, char num[])
-
{
-
struct stack *s = init_stack();
-
*count = 0;
-
char tmp[MAXVAL], ch;
-
ch = getchar();
-
while (ch != EOF) {
-
while (ch != EOF && ch != '/n') {
-
switch (ch) {
-
case '#':
-
pop(s);
-
break;
-
case '@':
-
clear_stack(s);
-
break;
-
default:
-
push(s, ch);
-
break;
-
}
-
ch = getchar();
-
}
-
-
int i, j;
-
bool empty;
-
-
i = 0;
- if (ch != EOF) {/*put the character '/n' in tmp array*/
-
tmp[i++] = ch;
-
ch = getchar();
-
}
- /*also put characters of every line in tmp array*/
-
for (; !(empty = stack_empty(s)); i++) {
-
tmp[i] = top(s);
-
pop(s);
-
}
-
for(j = i - 1; j >= 0; j--, (*count)++)
-
num[*count] = tmp[j];
-
}
-
destory_stack(s);
-
}
-
int main()
-
{
-
char num[MAXVAL];
-
int count, i;
-
-
lineedit(&count, num);
-
for (i = 0; i < count; i++)
-
putchar(num[i]);
-
return 0;
- }
(4)迷宫求解
思路:
do{
若 当前位置可通,// 可通只未曾走过的通道块。
则 {
将当前位置插入栈顶;//纳入路径
若该位置是出口位置,则结束;//求得的路径放在栈中
否则切换当前位置的东邻块(从东开始,顺时针方向)为新的当前位置;
}
否则,
若 栈不空但栈顶位置的四周均不可通,
则 {
删去栈顶位置;
若栈不空,则重新测试新的栈顶位置,
直到找到一个可通的的相邻块或出栈至栈空;
}
若 栈不空且栈顶位置尚有其他方向未经探索,
则 设定新的当前位置为顺时针方向旋转找到的栈顶位置的下一块相邻块;
}
数据结构:
这里用的栈的数据结构:
- /*stack.h*/
- #ifndef _STACK_H
- #define _STACK_H
- #define Type struct stack_elem*
- #define MAXVAL 100/*the max depth of stack*/
- #ifdef _MSC_VER
- #define bool int
- #define true 1
- #define false 0
- #else
- #include <stdbool.h>
- #include <stdint.h>
- #endif
-
struct stack_elem;
-
struct stack;
-
struct stack *init_stack();
-
void destory_stack(struct stack *s);
-
void push(struct stack *s, Type data);
-
void pop(struct stack *s);
-
Type top(struct stack *s);
-
int stack_size(struct stack *s);
-
bool stack_empty(struct stack *s);
-
void clear_stack(struct stack *s);
- #endif
- /*stack.c*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include "stack.h"
-
struct stack {
- int sp;/*the next free pos*/
-
Type val[MAXVAL];
-
};
-
struct stack *init_stack()
-
{
-
struct stack *s = (struct stack*)malloc(sizeof(struct stack));
-
if (s != NULL)
-
s->sp = 0;
-
return s;
-
}
-
void destory_stack(struct stack *s)
-
{
-
assert(s != NULL);
-
clear_stack(s);
-
free(s);
-
}
-
void push(struct stack *s, Type data)
-
{
-
assert(s != NULL);
-
if (s->sp < MAXVAL)
-
s->val[s->sp++] = data;
-
else
-
printf("error: stack full, can't push %p/n", data);
-
}
-
void pop(struct stack *s)
-
{
-
assert(s != NULL);
-
if (s->sp > 0) {
-
free(s->val[--s->sp]);
- } else
-
printf("error: stack empty!/n");
-
}
-
Type top(struct stack *s)
-
{
-
assert(s != NULL);
-
if (s->sp > 0)
-
return s->val[s->sp - 1];
-
else {
-
printf("error: stack empty!/n");
-
return 0;
-
}
-
}
-
void clear_stack(struct stack *s)
-
{
-
assert(s != NULL);
-
while (! stack_empty(s))
-
pop (s);
-
}
-
bool stack_empty(struct stack *s)
-
{
-
assert(s != NULL);
-
if (s->sp > 0)
-
return false;
- else
-
return true;
-
}
-
int stack_size(struct stack *s)
-
{
-
if (s == NULL)
-
return 0;
- else
-
return s->sp;
-
}
采用了指针数组,其中的指针指向了struct stack_elem结构体
其他数据结构:
-
struct stack_elem {
- int ord;/*the order of pass object in the way*/
- struct pos seat;/*the coordinate of pass object */
- int di;/*the direction: east--1, south--2, west--3, north--4*/
- };
主函数:
- #include <stdio.h>
- #include <stdlib.h>
- #include "stack.h"
- #define MAX_M 10
- /*record the pass object status: pass--0, block--1, walk--2, back--3*/
-
int status[MAX_M][MAX_M];
-
struct pos {
-
int x;
-
int y;
-
};
-
struct stack_elem {
- int ord;/*the order of pass object in the way*/
- struct pos seat;/*the coordinate of pass object */
- int di;/*the direction: east--1, south--2, west--3, north--4*/
-
};
-
void init_status(char maze[][MAX_M])
-
{
-
int i, j;
-
-
for (i = 0; i < MAX_M; i++) {
-
for (j = 0; j < MAX_M; j++) {
-
if (maze[i][j] == 002)
-
status[i][j] = 1;
- else
-
status[i][j] = 0;
-
}
-
}
-
}
-
void print_maze(char maze[][MAX_M])
-
{
-
int i, j;
-
for (i = 0; i < MAX_M; i++) {
-
for (j = 0; j < MAX_M; j++) {
-
printf("%c ", maze[i][j]);
-
}
-
printf("/n");
-
}
-
}
-
void print_status(int status[][MAX_M])
-
{
-
int i, j;
-
for (i = 0; i < MAX_M; i++) {
-
for (j = 0; j < MAX_M; j++) {
-
printf("%d ", status[i][j]);
-
}
-
printf("/n");
-
}
-
}
-
bool is_pass(struct pos *ps)
-
{
-
if (status[ps->x][ps->y] == 0)
-
return true;
- else
-
return false;
-
}
-
void foot_print(struct pos *ps)
-
{
-
status[ps->x][ps->y] = 2;
-
}
-
void make_print(struct pos ps)
-
{
-
status[ps.x][ps.y] = 3;
-
}
-
void next_pos(struct stack_elem *p, struct pos *p_curpos)
-
{
-
struct pos temp;
-
temp.x = p->seat.x;
-
temp.y = p->seat.y;
-
-
switch (p->di) {
-
case 1:
-
temp.y++;
-
break;
-
case 2:
-
temp.x++;
-
break;
-
case 3:
-
temp.y--;
-
break;
-
case 4:
-
temp.x--;
-
break;
-
default:
-
break;
-
}
-
-
p_curpos->x = temp.x;
-
p_curpos->y = temp.y;
-
}
-
-
struct stack *maze_path(char maze[][MAX_M], struct pos *start, struct pos *end)
-
{
-
struct stack *s = init_stack();
-
struct pos curpos;
-
struct pos *p_curpos = &curpos;
-
p_curpos->x = start->x;
-
p_curpos->y = start->y;
-
int curstep = 1, direction = 1;
-
-
do {
- if (is_pass(p_curpos)) {/*the current pos is passable*/
-
foot_print(p_curpos);
-
-
struct stack_elem *p = (struct stack_elem *)malloc(sizeof(struct stack_elem));
-
p->ord = curstep;
-
p->seat.x = p_curpos->x;
-
p->seat.y = p_curpos->y;
-
p->di = direction;
-
-
push(s, p);
-
- if (p_curpos->x == end->x && p_curpos->y == end->y)/*find the exit*/
-
return s;
-
-
next_pos(p, p_curpos);
-
curstep++;
- } else {/*the current pos is not passable*/
-
if (! stack_empty(s)) {
-
struct stack_elem *tip = top(s);
-
while (tip->di == 4 && !stack_empty(s)) {
-
make_print(tip->seat);
-
pop(s);
-
tip = top(s);
-
}
-
if (tip->di < 4) {
-
tip->di++;
-
next_pos(tip, p_curpos);
-
}
-
}
-
-
}
-
} while (! stack_empty(s));
-
return s;
-
}
-
void mark_maze(char maze[][MAX_M], struct stack *s)
-
{
-
struct stack_elem *tip;
-
char ch = 0;
-
-
while (! stack_empty(s)) {
-
tip = top(s);
-
switch (tip->di) {
-
case 1:
-
ch = 26;
-
break;
-
case 2:
-
ch = 25;
-
break;
-
case 3:
-
ch = 27;
-
break;
-
case 4:
-
ch = 24;
-
break;
-
default:
-
break;
-
}
-
maze[tip->seat.x][tip->seat.y] = ch;
-
pop(s);
-
}
-
}
-
int main()
-
{
-
char maze[MAX_M][MAX_M] = {
-
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
2, 0, 0, 2, 0, 0, 0, 2, 0, 2,
-
2, 0, 0, 2, 0, 0, 0, 2, 0, 2,
-
2, 0, 0, 0, 0, 2, 2, 0, 0, 2,
-
2, 0, 2, 2, 2, 0, 0, 0, 0, 2,
-
2, 0, 0, 0, 2, 0, 0, 0, 0, 2,
-
2, 0, 2, 0, 0, 0, 2, 0, 0, 2,
-
2, 0, 2, 2, 2, 0, 2, 2, 0, 2,
-
2, 2, 0, 0, 0, 0, 0, 0, 0, 2,
-
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
};
-
printf("init status:/nmaze:/n");
-
print_maze(maze);
-
printf("/n");
-
-
init_status(maze);
-
printf("status array:/n");
-
print_status(status);
-
-
struct pos start, end;
-
start.x = start.y = 1;
-
end.x = end.y = 8;
-
-
struct pos *p_start = &start, *p_end = &end;
-
struct stack *pass_way = maze_path(maze, p_start, p_end);
-
-
printf("/nfinal status:/nstatus array:/n");
-
print_status(status);
-
-
mark_maze(maze, pass_way);
-
printf("/n");
-
printf("maze:/n");
-
print_maze(maze);
-
-
destory_stack(pass_way);
-
return 0;
-
}
经purify检测,无内存泄露。运行截图:
最开始做表达式求值的时候,思路不太清晰,后来想了想,有两种方式:方式一:先把中缀表达式转成后缀表达式,然后再求值就方便多了;方式二:算符优先方式。
发觉细节处理上很麻烦,最开始打算用C写,用自己的栈。后来发现自己的栈跟数据类型有密切联系,由于不能用模板,所以两个不同数据类型的栈操作要实现两次,最后想到了用void*指针指向实际的数据,用的时候再转换,感觉增加了复杂度,又降低了效率,所以直接用C++的stack。
另外一个问题就是输入方式,一种用getchar(),但识别的时候由于要超前读取一个字符,所以要设置缓冲区。另一种是直接读入一行字符串,缺点是受到了数组大小的限制。本次采用的是第二种。
在对字符的处理方式上,这里选用获取到相应运算数时,存入字符数组,然后转换成double型。另一种就是变读入边处理,直接返回double型。
整体思路如下:
1、设置两个栈,一个称作optr,用于寄存运算符,另一个称作opnd,用于寄存操作数或运算结果。
2、从str字符数组开始扫描,若是操作数则进opnd栈,若是运算符则和optr栈的栈顶运算符比较优先级后作相应操作。直到整个表达式求职完毕(optr和当前读入的字符均为'=')。
代码如下:
- #include <iostream>
- #include <stack>
- #include <cctype>
-
using namespace std;
- #define MAXVAL 100 /* the max length of input string */
- #define NUMBER '0' /* mark for find a number */
-
char getop(char s[], char str[])
-
{
-
char c;
-
int i;
-
static int j = 0;
-
-
i = 0;
-
while ((s[0] = c = str[j]) == ' ' || c == '/t')
-
j++;
-
s[1] = '/0';
-
-
if (! isdigit(c) && c != '.') {
-
j++;
-
return c;
-
}
-
if (isdigit(c)) {
-
while (isdigit(s[++i] = c = str[++j]))
-
;
-
}
-
if (c == '.') {
-
while(isdigit(s[++i] = c = str[++j]))
-
;
-
}
-
s[i] = '/0';
-
return NUMBER;
-
}
-
int index(char c)
-
{
-
int ret;
-
switch (c) {
-
case '+':
-
ret = 0;
-
break;
-
case '-':
-
ret = 1;
-
break;
-
case '*':
-
ret = 2;
-
break;
-
case '/':
-
ret = 3;
-
break;
-
case '(':
-
ret = 4;
-
break;
-
case ')':
-
ret = 5;
-
break;
-
case '=':
-
ret = 6;
-
break;
-
default:
-
break;
-
}
-
return ret;
-
}
-
char precede(char top, char c, char priority[][7])
-
{
-
int i = 0, j =0;
-
i = index(top);
-
j = index(c);
-
return priority[i][j];
-
}
-
double operate(double a, char op, double b)
-
{
-
double ret = 0;
-
switch (op) {
-
case '+':
-
ret = a + b;
-
break;
-
case '-':
-
ret = a - b;
-
break;
-
case '*':
-
ret = a * b;
-
break;
-
case '/':
-
ret = a / b;
-
break;
-
default:
-
break;
-
}
-
return ret;
-
}
-
-
double evaluate_expression(char *str, char priority[][7])
-
{
-
stack<double> opnd;
-
stack<char> optr;
-
char c, s[MAXVAL], op, ch;
-
double a, b;
-
-
optr.push('=');
-
c = getop(s, str);
-
while (c != '=' || optr.top() != '=') {
-
if (c == NUMBER) {
-
opnd.push(atof(s));
-
c = getop(s, str);
-
} else {
-
switch (ch = precede(optr.top(), c, priority)) {
- case '<': /* the top element of stack optr has lower priority */
-
optr.push(c);
-
c = getop(s, str);
-
break;
- case '=': /* get off '(' and get next character */
-
optr.pop();
-
c = getop(s, str);
-
break;
- case '>': /* pop and push compute result */
-
op = optr.top();
-
optr.pop();
-
b = opnd.top();
-
opnd.pop();
-
a = opnd.top();
-
opnd.pop();
-
opnd.push(operate(a, op, b));
-
break;
-
default:
-
break;
-
}
-
}
-
}
-
return opnd.top();
-
}
-
int main()
-
{
-
char str[MAXVAL];
-
char priority[7][7] = {
- // + - * / ( ) =
- '>', '>', '<', '<', '<', '>', '>', // +
- '>', '>', '<', '<', '<', '>', '>', // -
- '>', '>', '>', '>', '<', '>', '>', // *
- '>', '>', '>', '>', '<', '>', '>', // /
- '<', '<', '<', '<', '<', '=', ' ', // (
- '>', '>', '>', '>', ' ', '>', '>', // )
- '<', '<', '<', '<', '<', ' ', '=' // =
-
};
-
gets(str);
-
double ret = evaluate_expression(str, priority);
-
printf("%g/n", ret);
-
return 0;
-
}