zoukankan      html  css  js  c++  java
  • 栈的应用举例

    栈的应用举例

    进制转换

    /* 进制转换,由十进制转换为8进制  */
    void conversion()
    {
        SLinkList S;
        SElemType e;
        InitStack(&S);
        int N;
        scanf("%d",&N);
        while (N) {
            Push(S,N%8);
            N /= 8;
        }
        /* 这时栈S刚好存放进制转换结果,把每一位按顺序pop出来就可以了 */
        while (!StackEmpty(S)) {
            Pop(S,&e);
            printf("%d",e);
        }
        DestoryStack(&S);
    }
    

    括号匹配检测

    /* 括号匹配检测 */
    void matching()
    {
        SLinkList S;
        SElemType e = 0;
        InitStack(&S);  /* 初始化栈空间 */
    
        int c;
        while ((c=getchar()) != '
    ') {
            if(c == '(' || c == '[')
                Push(S,c);
            if(c == ')' || c == ']') {
                GetTop(S,&e);       /* 获取栈顶元素 */
                if(c == ')' && e == '(')
                    Pop(S,&e);      /* 栈顶元素和当前元素匹配则弹出 */
                else if(c == ']' && e == '[')
                    Pop(S,&e);
                else {              /* 不匹配,则直接退出 */
                    printf("not pip
    ");
                    DestoryStack(&S);
                    return;
                }
            }
        }
        /* 最后检测栈是否空的 */
        if (!StackEmpty(S)) {
            printf("not pip
    ");
        }else {
            printf("good
    ");
        }
        DestoryStack(&S);    
    }
    

    行编辑程序

    /* 行编辑程序 */
    void LineEdit()
    {
        SLinkList S;
        SElemType e;
        char str[100];
        InitStack(&S);  /* 初始化栈空间 */
    
        int c;
        while((c=getchar()) != EOF) {
            if(c != '
    ') { /* 还没到达行尾 */
                if(c == '#')
                    Pop(S,&e);
                else if(c == '@')
                    ClearStack(S); /* 清空栈以撤消改行 */
                else
                    Push(S,c);      /* 将字符数据压入栈中 */
            }
            else {
                // ... 在这里已经接收到一行字符,实际中可以传送至调用过程的数据区
                int i = 0;
                while(!StackEmpty(S)) {
                    Pop(S,&e);      /* 弹出数据存放到数组中 */
                    str[i++] = e;
                }
                while (i>0)        /* 逆向打印数组内容 */
                    printf("%c",str[--i]);
                printf("
    ");
            }
        }
        DestoryStack(&S);  
    }
    

    迷宫求解

    假设迷宫是这样的,用一个二位数组代表地图得到

    示例代码如下

    
    /* 栈的元素类型替换成如下 */
    typedef struct {
        int ord;   
        PosType seat;   /* 通道块在地图中的坐标位置 */
        int di;         /* 从此通道走向下一个通道的方向 */
    } SElemType;
    
    typedef struct {
        int i;
        int j;
    }PosType;
    
    #define MAP_ROW 10
    #define MAP_COL 10
    
    /* 定义地图类型 */
    typedef int Map[MAP_ROW][MAP_COL];
    
    Map map = {
    //  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 0
        1, 0, 0, 1, 0, 0, 0, 1, 0, 1,  // 1
        1, 0, 0, 1, 0, 0, 0, 1, 0, 1,  // 2
        1, 0, 0, 0, 0, 1, 1, 0, 0, 1,  // 3
        1, 0, 1, 1, 1, 0, 0, 0, 0, 1,  // 4
        1, 0, 0, 0, 1, 0, 0, 0, 0, 1,  // 5
        1, 0, 1, 0, 0, 0, 1, 0, 0, 1,  // 6
        1, 0, 1, 1, 1, 0, 1, 1, 0, 1,  // 7
        1, 1, 0, 0, 0, 0, 0, 0, 0, 1,  // 8
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1   // 9
    };
    Map mfoot;    /* 辅助地图,用来保存足迹  */
    
    /* 打印地图 */
    void printMap(Map map)
    {
        /* 打印列数 */
        printf("   ");
        for(int i=0;i<MAP_COL;i++)
            printf("%d ",i);
        printf("
    ");
        for(int i=0;i<MAP_ROW;i++) {
            printf("%2d ",i); /* 打印行数 */
            for(int j=0;j<MAP_COL;j++)
                if(map[i][j] == 1) printf("▇ ");
                else if(map[i][j] == 2) printf("! ");
                else printf(". ");
            printf("
    ");
        }
    }
    
    /* 标记足迹 */
    void FootPrint(PosType pos)
    {
        mfoot[pos.i][pos.j] = 1;
    }
    
    int Pass(PosType pos)
    {
        if(mfoot[pos.i][pos.j] == 0 && map[pos.i][pos.j] == 0) 
            return TRUE;            /* 当前位置没有标记过,可以通过 */
        else 
            return FALSE;
    }
    
    /* 获取下一个位置 */
    PosType NextPos(PosType pos, int setp)
    {
        switch (setp)
        {
        case 1:
            pos.j++;
            break;
        case 2:
            pos.i++;
            break;
        case 3:
            pos.j--;
            break;
        case 4:
            pos.i--;
            break;
        default:
            break;
        }
        return pos;
    }
    
    int main()
    {
        SLinkList S; 
        SElemType e;
        InitStack(&S);  /* 初始化栈空间 */
    
        printMap(map);
    
        memset(mfoot,0,sizeof(Map)); /* 清空足迹 */
        PosType start = {1,1};
        PosType end = {8,8};
    
        PosType curpos = start;     /* 当前位置 */
        int curstep = 1;            /* 探索第一步 */
    
        do{
            if(Pass(curpos)) {      /* 当前通道块没有到达过,可通行 */
                FootPrint(curpos);  /* 留下足迹 */
                SElemType e = {curstep, curpos, 1};
                Push(S,e);          /* 加入路径 */
                if(curpos.i == end.i && curpos.j == end.j ) { /* 到达出口位置 */
                    printf("finsh
    ");
                    break;
                }
                // printf("pos (%d,%d)
    ",curpos.i,curpos.j);
                curpos = NextPos(curpos,1);  /* 对于没有探索过的模块,下一个位置是东 */
                curstep++;
            }
            else {  /* 当前位置不能通过 */
                if(!StackEmpty(S)) {
                    Pop(S,&e);      /* 弹出上一步的通道块元素 */
                    while(e.di == 5 && !StackEmpty(S)) {    /* 如果已经走完四个方向都不行 */
                        Pop(S,&e);  /* 再退出上一个 */
                    }
                }
                if(e.di < 5) {
                    e.di++;
                    Push(S,e);
                    curpos = NextPos(e.seat,e.di); /* 换下一个地方探索 */
                }
            }
        }while(!StackEmpty(S));
    
        while(!StackEmpty(S)) {
            Pop(S,&e);
            map[e.seat.i][e.seat.j] = 2;
        }
        printMap(map);
        DestoryStack(&S);
    }
    

    最后结果如下

    表达式求值

    
    /**
     * 首先操作数栈为空栈,表达式起始符'#'为运算符栈栈底元素
     * 依次读入表达式中每一个字符,若是操作数,则进OPND,若是运算符,则和OPTR栈的栈顶运算符比较优先级后
     * 做相应的操作,直至整个表达式求值完毕(即OPTR栈顶元素变成'#')
     */
    
    int isOPTR(int c) 
    {
        if(c>='0' && c<='9')
            return FALSE;
        else 
            return TRUE;
    }
    
    /** 为了先算括号内的表达式,则符号( 还没入栈时则优先入栈,所以它在外面时总是最大的,
     * 而当 ( 符号已经在栈里面,和其他符号比较时它又是最小的,必须让其他元素先进来
     * 符号 )本身不入栈,一直在外面,所以优先级最高
     * 除了栈外的( ,栈内的乘除优先级最高,因为除了括号外,总是需要先算括号,那么算括号就得让栈外 ( 先入栈 
     * 已经在栈内的 ( ,也就是说也就在括号里面,则优先级看 
     * 
     * 由规则3 
     */
    int Optr_Table[7][7] = {
    //       +    -    *    /    (    )    #
    // +
            '>', '>', '<', '<', '<', '>', '>',
    // -
            '>', '>', '<', '<', '<', '>', '>', 
    // *
            '>', '>', '>', '>', '<', '>', '>',
    // /
            '>', '>', '>', '>', '<', '>', '>',
    // (
            '<', '<', '<', '<', '<', '=', ' ',
    // ) 
            '>', '>', '>', '>', ' ', '>', '>',
    // #  
            '<', '<', '<', '<', '<', ' ', '=' 
    };
    
    
    int getIndex(int c)
    {
        switch (c) {
            case '+': return 0;
            case '-': return 1;
            case '*': return 2;
            case '/': return 3;
            case '(': return 4;
            case ')': return 5;
            case '#': return 6;
            default:
                return 7;
        }
    }
    
    /* 比较两个运算符的优先级 */
    int Precede(int c1, int c2)
    {
        c1 = getIndex(c1);
        c2 = getIndex(c2);
        if(c1>6 || c2 >6)
            return ' ';
        return Optr_Table[c1][c2];
    }
    
    /* 计算操作 */
    int Operate(int a, int theta, int b)
    {
        switch (theta) {
            case '+': return a + b;
            case '-': return b - a;
            case '*': return a * b;
            case '/': return a / b;
            default:
                return 0;
        }
    }
    
    
    int main()
    {   
        SLinkList OPTR;     /* 寄存运算符 */
        SLinkList OPND;     /* 寄存操作数或运算结果 */
        SElemType e;
        SElemType top;
    
        InitStack(&OPTR);   /* 初始化栈空间 */
        InitStack(&OPND);
        Push(OPTR,'#');
    
        GetTop(OPTR,&top);
        int a,b;
        int c = getchar();
        while(c != '#' || top != '#') {  /* 一个表达式还没结束,或者运算符还没到底 */
            if(!isOPTR(c)) {
                Push(OPND,c-'0'); /* 不是运算符,压入操作数栈中 */
                c = getchar();
            }
            else {
                GetTop(OPTR,&e);
                switch (Precede(e,c)) /* 栈顶运算符和当前运算符比较优先级 */
                {
                    case '<' :        /* 栈顶元素优先级低 */
                        Push(OPTR,c);
                        c = getchar();
                        break;
                    case '=' :        /* 脱括号并接收下一个字节  */
                        Pop(OPTR,&e);
                        c = getchar();
                        break;
                    case '>' :        /* 运算符出栈并将计算结果如入栈 */
                        Pop(OPTR,&e);
                        Pop(OPND,&a);
                        Pop(OPND,&b);
                        Push(OPND,Operate(a,e,b));
                        break;
                    default:
                        break;
                }
            }
            GetTop(OPTR,&top);
        }
        
        GetTop(OPND,&e);
        printf("result: %d
    ",e);
        DestoryStack(&OPTR);
        DestoryStack(&OPND);
    }
    
  • 相关阅读:
    Calendar.getInstance()获取当天指定点上的时间
    Timer和TimerTask详
    YYC松鼠短视频系统上传视频会被压缩的问题如何解决?
    YYC松鼠短视频系统上传视频会被压缩的问题如何解决?
    亲测-分享最新微信付费进群收费进群系统源码-附带搭建教
    亲测-分享最新微信付费进群收费进群系统源码-附带搭建教
    如何批量删除通一个文件夹目录下的相同文件,批量删除文件
    【干货】零基础30分钟让你拥有一个完整属于自己的短视频APP系统
    【干货】零基础30分钟让你拥有一个完整属于自己的短视频APP系统
    【bug】YYC松鼠短视频点击上传视频 提示错误的 或无反应
  • 原文地址:https://www.cnblogs.com/wjundong/p/11624058.html
Copyright © 2011-2022 走看看