e.g.1 数制转换

十进制数N和其它d进制数的转换是计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理。

假设编写一个程序:对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数。由于上述计算过程是从低位到高位顺序产生八进制数的各个数位,而打印输出,一般来说应从高位到低位进行,恰好和计算过程相反。因此,若将计算过程中得到的八进制数的各为顺序进栈,则按出栈序列打印输出的即为与输入对应的八进制数。

e.g.2 括号匹配

假设表达式中运行包含两种括号:圆括号和方括号,其嵌套的顺序随意,即([]())或[([])[]]等为正确的格式,[(])或([()]或为不正确的格式。可利用栈来检验括号是否匹配。

e.g.3 行编辑程序

一个简单的行编辑程序的功能:接受用户从终端输入的程序或数据,并存入用户的数据区。由于用户在终端上进行输入时,不能保证不出差错,当用户发现刚刚键入的一个字符是错的时,可补进一个退格符#,表示前一个字符无效;如果发现当前键入的行内差错较多或难以补救,则可以键入一个退格符@,表示当前行中的字符均无效。

e.g.4 表达式求值

可以使用两个工作栈。一个称为OPTR,用来存运算符(+=*/()#); 另一个称为OPND,用来存放操作数或运算结果。算法的基本思想是:

(1)   首先将操作数栈置为空栈,表达式起始符#为运算法栈的栈底元素;

(2)   依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为#)

e.g.5 迷宫求解

求迷宫中从入口到出口的路径:(如下图)

     

代码实现

 #include <stdio.h>
#include <stdlib.h>
#include <string.h> #define STACK_INIT_SIZE 100
#define STACKINVREMENT 10
typedef char SElemType;
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
}SqStack; static int InitStack(SqStack *S);
static int GetTop(SqStack *S, SElemType *e);
static int Push(SqStack *S, SElemType e);
static int Pop(SqStack *S, SElemType *e);
static int StackTraversie(SqStack S);
static int StackEmpty(SqStack S);
static int ClearStack(SqStack *S);
static int DestoryStack(SqStack *S); static void conversion()
{
int N = ;
SElemType E;
SqStack S;
InitStack(&S);
printf("请输入一个十进制数:");
scanf("%d", &N);
while(N){
Push(&S, ''+N%);
N=N/;
}
printf("该数的八进制数为:");
while(StackEmpty(S)<){
Pop(&S, &E);
printf("%c", E);
}
printf("\n");
} static int bracketMatch()
{
SElemType e;
SqStack S;
InitStack(&S); int err = ;
char string[] = {};
char *c = string;
printf("输入待检验的字符串:");
scanf("%s[^\\n]", string);
while(*c){
switch(*c){
case '[':
case '(':
Push(&S, *c);
break;
case ']':
if((!GetTop(&S, &e)) && (e == '[')){
Pop(&S, &e);
}else{
err = -;
goto end;
}
break;
case ')':
if((!GetTop(&S, &e)) && (e == '(')){
Pop(&S, &e);
}else{
err = -;
goto end;
}
break;
default:
err = -;
goto end;
}
c++;
}
end:
if(err<){
printf("%s 是不匹配的!\n", string);
}else{
printf("%s 是匹配的!\n", string);
}
return err;
} static void lineEdit()
{
SElemType e;
SqStack S;
InitStack(&S); char line[] = {};
char data[] = {};
char *c = line;
printf("输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):");
scanf("%s[^\\n]", line);
if(strncmp(line, "end", strlen("end")) == ){
return ;
}
while(*c){
if(*c == '!'){
DestoryStack(&S);
break;
}
switch(*c){
case '#':
Pop(&S, &e);
break;
case '@':
ClearStack(&S);
break;
default:
Push(&S, *c);
break;
}
c+=;
if(!(*c)){
printf("输出字符:%s\n", S.base);
ClearStack(&S);
memset(line, , sizeof(line));
printf("输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):");
scanf("%s[^\\n]", line);
if(strncmp(line, "end", strlen("end")) == ){
return;
}
c = line;
}
}
} static int IsOPTR(char c, char OP[], int len)
{
int i = ;
for(i=; i<len; i++){
if(c == OP[i]){
return ;
}
}
return -;
} static char Precede(char c1, char c2)
{
int I[] = {};
I['+'] = ;
I['-'] = ;
I['*'] = ;
I['/'] = ;
I['('] = ;
I[')'] = ;
I['#'] = ;
char table[][] = {};
table[I['+']][I['+']] = '>';table[I['+']][I['-']] = '>';table[I['+']][I['*']] = '<';table[I['+']][I['/']] = '<';table[I['+']][I['(']] = '<';table[I['+']][I[')']] = '>';table[I['+']][I['#']] = '>';
table[I['-']][I['+']] = '>';table[I['-']][I['-']] = '>';table[I['-']][I['*']] = '<';table[I['-']][I['/']] = '<';table[I['-']][I['(']] = '<';table[I['-']][I[')']] = '>';table[I['-']][I['#']] = '>';
table[I['*']][I['+']] = '>';table[I['*']][I['-']] = '>';table[I['*']][I['*']] = '>';table[I['*']][I['/']] = '>';table[I['*']][I['(']] = '<';table[I['*']][I[')']] = '>';table[I['*']][I['#']] = '>';
table[I['/']][I['+']] = '>';table[I['/']][I['-']] = '>';table[I['/']][I['*']] = '>';table[I['/']][I['/']] = '>';table[I['/']][I['(']] = '<';table[I['/']][I[')']] = '>';table[I['/']][I['#']] = '>';
table[I['(']][I['+']] = '<';table[I['(']][I['-']] = '<';table[I['(']][I['*']] = '<';table[I['(']][I['/']] = '<';table[I['(']][I['(']] = '<';table[I['(']][I[')']] = '=';table[I['(']][I['#']] = ' ';
table[I[')']][I['+']] = '>';table[I[')']][I['-']] = '>';table[I[')']][I['*']] = '>';table[I[')']][I['/']] = '>';table[I[')']][I['(']] = ' ';table[I[')']][I[')']] = '>';table[I[')']][I['#']] = '>';
table[I['#']][I['+']] = '<';table[I['#']][I['-']] = '<';table[I['#']][I['*']] = '<';table[I['#']][I['/']] = '<';table[I['#']][I['(']] = '<';table[I['#']][I[')']] = ' ';table[I['#']][I['#']] = '=';
return table[I[c1]][I[c2]];
} static char Operate(char a, char theta, char b)
{
int i = atoi(&a);
int j = atoi(&b);
int ret = ;
if(theta == '+'){
ret = i+j;
}
if(theta == '-'){
ret = i-j;
}
if(theta == '*'){
ret = i*j;
}
if((theta=='/') && (j!=)){
ret = i/j;
}
return (char)(ret+'');
} static int EvaluateExpression()
{
SElemType e;
SqStack OPTR;
SqStack OPND;
InitStack(&OPTR); //操作符
InitStack(&OPND); //操作数
Push(&OPTR, '#');
char line[] = {};
char *c = line;
char OP[] = "+-*/()#", theta, a, b;
printf("输入仅含有运算符+-*/()的表达式,若有#则表示结束输入, 只支持10以内的运算:");
scanf("%s[^\\n]", line);
while(*c){
if(IsOPTR(*c, OP, sizeof(OP))<){
Push(&OPND, *c);
c+=;
}else{
GetTop(&OPTR, &e);
switch(Precede(e, *c)){
case '<':
Push(&OPTR, *c);
c+=;
break;
case '=':
Pop(&OPTR, &e);
c+=;
break;
case '>':
Pop(&OPTR, &theta);
Pop(&OPND, &b);
Pop(&OPND, &a);
Push(&OPND, Operate(a, theta, b));
break;
default:
break;
}
}
}
GetTop(&OPND, &e);
printf("结果 %s = %c\n", line, e);
return ;
} int main(int argc, char *argv[])
{
printf("e.g.1: 任意一个十进制数转换成八进制树.\n");
conversion(); printf("e.g.2: 检验括号是否匹配.\n");
bracketMatch();
bracketMatch(); printf("e.g.3: 行编辑程序.\n");
lineEdit(); printf("e.g.4: 表达式求值.\n");
EvaluateExpression(); return ;
} static int InitStack(SqStack *S)
{
if((S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType))) == NULL){
printf("failed malloc when initSTack!\n");
return -;
}
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return ;
} static int GetTop(SqStack *S, SElemType *e)
{
if(S->top == S->base){
return -;
}
(*e) = *(S->top-);
return ;
} static int Push(SqStack *S, SElemType e)
{
if((S->top - S->base) >= S->stacksize){
if((S->base=(SElemType*)realloc(S->base, (S->stacksize+STACKINVREMENT)*sizeof(SElemType))) == NULL){
printf("failed reamalloc when Push!\n");
return -;
}
S->top = S->base+S->stacksize;
S->stacksize += STACKINVREMENT;
}
*(S->top++) = e;
return ;
} static int Pop(SqStack *S, SElemType *e)
{
if(S->top == S->base){
return -;
}
(*e) = *(--S->top);
return ;
} static int StackTraversie(SqStack S)
{
SElemType *p = S.base;
printf("base is 0x%x, top is 0x%x\n", S.base, S.top);
while(p)
{
if(p == S.top){
break;
}
printf("0x%x, %c\n", p, *p);
p++;
}
return ;
} static int StackEmpty(SqStack S)
{
if(S.top == S.base){
return ;
}else{
return -;
}
} static int ClearStack(SqStack *S)
{
if(S==NULL){
return -;
}
memset(S->base, , S->stacksize);
S->top = S->base;
return ;
} static int DestoryStack(SqStack *S)
{
if(S == NULL){
return -;
}
if(S->base){
free(S->base);
S->base = NULL;
S->top = NULL;
S->stacksize = ;
}
return ;
}

栈的应用1-2-3-4

 //
// Created by lady on 19-3-27.
// #include <stdlib.h>
#include <stdio.h>
#include <string.h> #define YES 1
#define NO 0
#define MAX_SIZE 10
typedef struct position{
int Xaxis; //横坐标
int Yaxis; //纵坐标
}position;
typedef struct brick{
int type; //yes: 表示通过; no: 表示障碍物或墙
int visit; //no: 表示未曾到过; yes: 表示已经来过
}brick; typedef struct matrix{
int w; //宽度
int h; //高度
brick wall[MAX_SIZE][MAX_SIZE];
position in; // 入口
position out; // 出口
}matrix; /////////////////////////////
#define STACK_INIT_SIZE 100 //栈的初始大小
#define STACK_INVREMENT 10 //栈的增量大小
typedef struct SElemType{
int ord; //序号
position seat; //位置坐标
int di; //方向
}SElemType;
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
static int InitStack(SqStack *S); //栈的初始化
static int Push(SqStack *S, SElemType e); //入栈
static int Pop(SqStack *S, SElemType *e); //出栈
static int StackEmpty(SqStack S); //判断栈是否为空
///////////////////////////// //创建一个迷宫矩阵
int create_matrix(matrix *array)
{
int i = ;
int j = ;
memset(array->wall, , sizeof(array->wall)); array->w = ;
array->h = ; brick b;
b.type = YES;
b.visit = NO;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = b;
array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = array->wall[][] = b;
array->in.Xaxis = ;
array->in.Yaxis = ;
array->out.Xaxis = ;
array->out.Yaxis = ;
return ;
} //打印迷宫矩阵,红色表示墙或者障碍物,绿色表示通道,蓝色表示迷宫中从入口到出口的一条路径
void print_matrix(matrix *array)
{
int i = ;
int j = ;
printf("%c\t", ' ');
for(i=; i<array->w; i++){
printf("%d\t", i);
}
printf("\n");
for(i=; i<array->h; i++){
printf("%d\t", i);
for(j=; j<array->w; j++){
if(array->wall[i][j].visit){//蓝色
printf("\033[1;30;44m%d\t\033[0m", array->wall[i][j].visit);
}else if(array->wall[i][j].type == YES){//绿色
printf("\033[1;30;42m%d\t\033[0m", array->wall[i][j].type);
}else{//红色
printf("\033[1;30;41m%d\t\033[0m", array->wall[i][j].type);
}
}
printf("\n");
}
} //判断迷宫array中的位置pos是否可以通过,即是通道还是障碍物
static int Pass(position pos, matrix *array)
{
int x = pos.Xaxis;
int y = pos.Yaxis;
int type = array->wall[x][y].type;
int visit = array->wall[x][y].visit;
if( type== YES ){
if(visit == NO){
return ;
}
}
return ;
} //在迷宫array的位置pos上留下来过的痕迹
static int FootPrint(position pos, matrix *array)
{
int x = pos.Xaxis;
int y = pos.Yaxis;
array->wall[x][y].visit = YES;
return ;
} //在迷宫array的位置pos上留下来过的痕迹
static int MarkPrint(position pos, matrix *array)
{
int x = pos.Xaxis;
int y = pos.Yaxis;
array->wall[x][y].visit = YES;
return ;
} //返回位置pos的下一个探测的"通道"
static position NextPos(position pos, int direct)
{
position p;
if(direct == ){
p.Xaxis = pos.Xaxis;
p.Yaxis = pos.Yaxis-;
}
if(direct == ){
p.Xaxis = pos.Xaxis + ;
p.Yaxis = pos.Yaxis;
}
if(direct == ){
p.Xaxis = pos.Xaxis;
p.Yaxis = pos.Yaxis + ;
}
if(direct == ){
p.Xaxis = pos.Xaxis - ;
p.Yaxis = pos.Yaxis;
}
return p;
} //寻找迷宫array中从入口到出口的一条路径
static int Find_Path(matrix *array)
{
SqStack S;
position curpos = array->in; //设定当前位置
position end = array->out;
SElemType e;
int curstep = ; //探索第一步
int flag = ;
int x, y;
int i, j;
InitStack(&S); //初始化栈 do{
if(Pass(curpos, array)){//当前位置可以通过,即使未来过的通道
FootPrint(curpos, array);//留下到过的足迹
e.ord = curstep;
e.seat = curpos;
e.di = ;
Push(&S, e); //加入路径
if((curpos.Xaxis == end.Xaxis) && (curpos.Yaxis == end.Yaxis)){//到达终点
flag = ;
break;
}
curstep += ;//探索下一步
}else{//当前位置不能通过
if(StackEmpty(S)<){
Pop(&S, &e);
while((e.di == ) && (StackEmpty(S) < )){
MarkPrint(e.seat, array);//留下不能通过的足迹
Pop(&S, &e);
}
if(e.di < ){
e.di += ;//换下一个方向探索
Push(&S, e);
curpos = NextPos(e.seat, e.di);//设定当前位置是该块新方向上的相邻块
}
}
}
}while(StackEmpty(S)<); //清空迷宫中的块的visit标记
for(i=; i<array->w; i++){
for(j=; j<array->h; j++){
array->wall[i][j].visit = NO;
}
} //foreach stack
if(flag){//有入口到出口的路径
SElemType *p = S.base;
while(p){
if(p==S.top){
break;
}
x = p->seat.Xaxis;
y = p->seat.Yaxis;
//将迷宫中的块的visit标记来表示路径上的序号
array->wall[x][y].visit = p->ord;
p += ;
}
return ;
}else{
return -;
}
} int main(int argc, char *argv[])
{
matrix array;
if(create_matrix(&array) < ){
return -;
}
Find_Path(&array);
print_matrix(&array);
return ;
} /////////////////////////////
static int InitStack(SqStack *S)
{
if((S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType))) == NULL){
return -;
}
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
return ;
} static int Push(SqStack *S, SElemType e)
{
if((S->top - S->base) >= S->stacksize){
if((S->base=(SElemType*)realloc(S->base, (S->stacksize+STACK_INVREMENT)*sizeof(SElemType))) == NULL){
printf("failed reamalloc when Push!\n");
return -;
}
S->top = S->base+S->stacksize;
S->stacksize += STACK_INVREMENT;
}
*(S->top++) = e;
return ;
} static int Pop(SqStack *S, SElemType *e)
{
if(S->top == S->base){
return -;
}
(*e) = *(--S->top);
return ;
}
static int StackEmpty(SqStack S)
{
if(S.top == S.base){
return ;
}else{
return -;
}
}
/////////////////////////////

e.g.5 迷宫求解

代码运行

 /home/lady/CLionProjects/untitled/cmake-build-debug/untitled
e.g.1: 任意一个十进制数转换成八进制树.
请输入一个十进制数:123
该数的八进制数为:173
e.g.2: 检验括号是否匹配.
输入待检验的字符串:[([][])]
[([][])] 是匹配的!
输入待检验的字符串:(()]
(()] 是不匹配的!
e.g.3: 行编辑程序.
输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):whli##ilr#e(s#*s)
输出字符:while(*s)
输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):outchar@putchar(*s=#++)
输出字符:putchar(*s++)
输入字符串(其中#表示上一个字符无效,@表示此此行该字符前的所有字符无效, end表示结束):end
e.g.4: 表达式求值.
输入仅含有运算符+-*/()的表达式,若有#则表示结束输入, 只支持10以内的运算:3*(7-5)#
结果 3*(7-5)# = 6 Process finished with exit code 0

栈->栈的应用的更多相关文章

  1. PQJ 1686(栈栈栈)

    PQJ  1686(栈栈栈) 用栈解决问题 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I6 ...

  2. Java数据结构与算法(3) - ch04栈(栈和转置)

    栈的基本特性是后进先出,最简单的用途是用于转置,还有其他诸如括号匹配,中序表达式(A+B*(C-D/(E+F)) --> ABCDEF+/-*+)和后续表达式(345+*612+/- --> ...

  3. java虚拟机 jvm 出入java栈 栈空间内存分配

    java栈空间是一块线程私有的内存空间,java堆和程序数据密切相关,那么java栈就是和线程执行密切相关.线程最基本的执行行为就是函数的调用.每次函数调用其实是通过java栈传递数据的. 数据结构中 ...

  4. 栈->栈与递归

    文字简述 1.阶乘函数 2.2阶Fiibonacci数列 3.n阶Hanoi塔问题 代码实现 // // Created by lady on 19-4-3. // #include <stdi ...

  5. 栈->栈的基本定义

    定义: 栈是限定仅在表尾进行插入或删除操作的线性表.因此,对栈来说,表尾端有特殊含义,称为栈顶,相应地,表头端称为栈底.不含元素的空表成为空栈. 示意图: 顺序栈的表示和实现 可以在初始化时分配一块连 ...

  6. 剑指offer-包含min函数的栈-栈和队列-python

    题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)).   # -*- coding:utf-8 -*- class Solution: de ...

  7. 剑指offer-面试题30-包含min函数的栈-栈

    /* 题目: 定义栈的数据结构,实现一个能够得到栈的最小元素的min函数. */ /* 思路: 错误思路:每次保存当前最小的元素,如果当前最小元素弹出,最小元素是谁? 正确思路:两个栈,一个栈保存数据 ...

  8. Java虚拟机栈--栈帧

    栈帧的内部结构 每个栈帧中存储着 1.局部变量表(Local Variables) 2.操作数栈(Operand Stack)(或表达式栈) 3.动态链接(Dynamic Linking)(或执行&q ...

  9. 匹夫细说C#:不是“栈类型”的值类型,从生命周期聊存储位置

    0x00 前言: 匹夫在日常和别人交流的时候,常常会发现一旦讨论涉及到“类型”,话题的热度就会立马升温,因为很多似是而非.或者片面的概念常常被人们当做是全面和正确的答案.加之最近在园子看到有人翻译的& ...

随机推荐

  1. ES进阶--01

    第2节结构化搜索_在案例中实战使用term filter来搜索数据 课程大纲 1.根据用户ID.是否隐藏.帖子ID.发帖日期来搜索帖子 (1)插入一些测试帖子数据 POST /forum/articl ...

  2. LabVIEW--使用云端编译器编译多个vi

    使用ni 云服务器编译vi 详细请看链接: https://users.niwsc.com/compilecloud/#/ http://www.ni.com/white-paper/52328/en ...

  3. SlopeOne

    相信大家对如下的Category都很熟悉,很多网站都有类似如下的功能,“商品推荐”,"猜你喜欢“,在实体店中我们有导购来为我们服务,在网络上 我们需要同样的一种替代物,如果简简单单的在数据库 ...

  4. Python3 元组(tuple)

    一.定义:不可变序列的数据元素集合,元组的元素是不可以修改的 元组使用小括号,例如:tuple = (1,) 注意:即使元组里面只有一个元素,该元素后面也要加 ",":在函数传递参 ...

  5. OrCAD Capture CIS 16.6 将版本16.6的设计文件另存为版本16.2的设计文件

    操作系统:Windows 10 x64 工具1:OrCAD Capture CIS 16.6-S062 (v16-6-112FF) 启动OrCAD Capture CIS,打开.dsn设计文件,右击该 ...

  6. Windows Internals 笔记——CreateProcess

    1.一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1.然后系统为新进程的主线程创建一个线程内核对象(使其计数为1). 2.CreateProcess在进程完全初 ...

  7. Python面向对象之-反射

    Python中一切皆对象,在Python中的反射:通过字符串的形式操作对象的属性 hasattr  判断是否有改属性或者方法,有返回True,没有返回false getattr  如果是属性获得该属性 ...

  8. Go Socket实现简单的HttpServer

    在上篇博客中写到如何用Python实现一个类似tomcat的简单服务器,接下来用go语言去实现 1. Go本身自己封装实现了非常简单的httpServer package main import ( ...

  9. windows和linux换行规则的区别

    在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符.但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符.要是在这 ...

  10. UOJ#314. 【NOI2017】整数 其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ314.html 题解 如果只加不减,那么瞎势能分析一波可以知道暴力模拟的复杂度是对的. 但是有减法怎么办? ...