• 广大考研数据结构复习之栈


    王道书籍上栈的基本操作和课后部分习题

    代码如下:

    /**
     * @author Dawn
     * @date 2019年11月9日21:52:16
     * @version 1.0
     * 栈的复习,由于函数不是很多,就写在一起算了
     */
    #include<stdio.h>
    #include<stdlib.h>
    
    #define MaxSize 50//栈中元素最大个数
    typedef int ElemType;
    
    typedef struct {
        ElemType data[MaxSize];//存放栈中元素
        int top;//栈顶指针
    }SqStack;
    
    //仅仅是为了写第四题
    typedef struct LNode{
        ElemType data;
        struct LNode* next;
    }LNode,*LinkList;
    
    //仅仅为了第五题 共享栈
    typedef struct {
        ElemType data[MaxSize];//共享栈
        int top[2];//2个栈顶指针
    }ShareStack;
    
    //============栈的基本操作定义===============
        //1.初始化
    void InitStack(SqStack& S);
    //2.判栈空
    bool StackIsEmpty(SqStack S);
    //3.进栈
    bool Push(SqStack& S, ElemType x);
    //4.出栈
    bool Pop(SqStack& S,ElemType &x);
    //5.读栈顶元素,将读取的结果放在x中
    bool GetTop(SqStack S, ElemType& x);
    int arrlen(int arr[]) {
        int length = 0;
        while (arr[length]>0) {
            length++;
        }
        return length;
    }
    
    //============课后习题定义===============
    //3.简陋版的符号匹配问题,也就是只有一种括号()。
    bool Judge(char A[]);
    bool Judge2(char A[]);
    //这里进行升级,也就是判断([()()])这种的问题 将(看成 1 。[ 看成 2 。)看成 11。]看成22
    bool Judge3(int A[]);
    //4.判断一个链表是否对称,用栈的思想来完成
    bool IsSymmetry(LinkList L,int n);
    //5.共享栈的设计,包括它的入栈和出栈操作
    //i 表示栈号(0,1这2个栈),x表示入栈的元素
    bool Push_S(ShareStack& S, int i, ElemType x);
    bool Pop_S(ShareStack& S, int i, ElemType& x);
    
    int main() {
        int arr[5] = { 1,2,3,4,5 };
        SqStack S;
        int i = 0;
        int x;
    
        //InitStack(S);
        //printf("栈是否为空:%s
    ", StackIsEmpty(S) ? "为空" : "不为空");
        //while (i < 5) {
        //    Push(S, arr[i++]);
        //}
        //printf("栈是否为空:%s
    ", StackIsEmpty(S) ? "为空" : "不为空");
    
        ////GetTop(S, x);
        ////printf("栈顶元素为:%d", x);
        //Pop(S, x);
        //printf("出栈的元素为:%d", x);
    
        ////课后习题测试
        //printf("
    ");
        //char A[7] = { 'O','O','I','I','O','O' };
        ////Judge(A);
        //Judge2(A);
        int arr2[] = { 1,2,1,11,1,11,22,11 }; //([()()])
        int len = arrlen(arr2);
        printf("length: %d
    ", len);
        printf("括号是否正确:%s
    ", Judge3(arr2) ? "正确" : "错误");
        return 0;
    }
    
    //============课后习题实现===============
    //3.算是栈的应用 简陋版的符号匹配问题,
    bool Judge(char A[]) {
        //思路?遍历数组,用 j k分别代表入栈I和出栈O的个数。然后通过这个次数来判断是否符合栈的规则
        int i = 0;
        int j = 0, k = 0;
    
        while (A[i] != '') {
            switch (A[i])
            {
            case 'I':
                j++;//个数加1
                break;//退出switch
    
            case 'O':
                k++;
                if (k > j) {//当出栈大于入栈,则返回false
                    printf("序列非法
    ");
                    return false;
                }
    
            }//wtitch
    
            i++;//判断下一个元素
        }
    
        if (j != k) {
            //如果倒数第二次次是j = k,最后一次进去是I加了一个1,还有其他情况,懒得举例子了
            printf("序列非法
    ");
            return false;
        }
        else {
            printf("序列合法
    ");
            return true;
        }
    }
    //使用栈来实现
    bool Judge2(char A[]) {
        int i = 0;
        int sum = 0;//这个sum就代替栈的意思
        while (A[i] != '') {
            if (sum == -1) {
                printf("序列不合法
    ");
                return false;
            }
            else {
                //2中情况
                if (A[i] == 'I') {
                    sum++;
                }
                else {
                    sum--;
                }
            }
    
            i++;//判断下一个元素
        }
    
        //如果上面通过了,还有入栈多余出栈的结果,或者倒数第二次循环的时候是s==0,最后一次就成了s==-1。然而没有进入循环中去
        if (sum != 0) {
            printf("序列不合法
    ");
            return false;
        }
        else {
            printf("序列合法
    ");
            return true;
        }
    }
    //这里进行升级,也就是判断([()()])这种的问题 将(看成 1 。[ 看成 2 。)看成 11。]看成22  ==>数组表示为:[1,2,1,11,1,11,22,11]
    bool Judge3(int A[]) {
        SqStack s;
        InitStack(s);
        //获取到栈的长度,([()()]) 这里默认就是8了.不同数组测试的时候记得改长度
        //int len = 8;
        int len = arrlen(A);
        int x;//出栈的元素
        for (int i = 0; i < len; i++) {
            switch (A[i])
            {
            case 1:
            case 2:
                //如果是这2种情况,就入栈
                Push(s, A[i]);
                break;
    
            case 11:
                Pop(s, x);
                if (x != 1)
                    return false;
                break;
            case 22:
                Pop(s, x);
                if (x != 2)
                    return false;
                break;
            
            }
        }
    
        if (StackIsEmpty(s))
            return true;
        else
            return false;
    }
    //4.判断一个带头节点链表是否对称,用栈的思想来完成
    bool IsSymmetry(LinkList L,int n) {
        int i;
        char s[10];//char s[n / 2];不能用变量,就用10随便表示一下吧
        LNode* p = L->next;
        for (i = 0; i < n / 2; i++) {
            s[i] = p->data;
            p = p->next;
        }
    
        i--;//恢复最后i值
        if (n % 2 == 1)
            p = p->next;//如果是奇数,后移到中心节点后的一个位置
        while (p != NULL && s[i] == p->data) {
            i--;
            p = p->next;
        }
    
        if (i == -1) {
            return true;
        }
        else {
            return false;
        }
    }
    //5.共享栈的设计,包括它的入栈和出栈操作
    //i 表示栈号(0,1这2个栈),x表示入栈的元素
    bool Push_S(ShareStack& S, int i, ElemType x) {
        //判断输入的i是否正确
        if (i < 0 || i>1)
            return false;
        //是否栈满
        if (S.top[1] - S.top[0] == 1)
            return false;
    
        //k开始入栈
        switch (i) {
        case 0:
            S.data[++S.top[0]] = x;
            return true;
            break;//第一个操作了就不要操作第二个了。。。其实这个这个break都是多余的,不过加上显得更加有逻辑性。因为有return.只要经过了return,就退出去了,根本不得执行那个break了
        case 1:
            S.data[--S.top[1]] = x;
            return true;
        }
    }
    bool Pop_S(ShareStack& S, int i, ElemType& x) {
        if (i < 0 || i>1)
            return false;
    
        switch (i)
        {
            //对于此处的case语句结束之后要不要加break,可以不要加,因为这个的return 可以直接返回出去了,
        case 0:
            if (S.top[0] == -1)
                return false;//0栈为空
            else {
                x = S.data[S.top[0]--];
                return true;
            }
                
    
        case 1:
            if (S.top[1] == MaxSize)
                return false;
            else {
                x = S.data[S.top[1]--];
                return true;
            }
                
        }
    }
    
    
    
    //============栈的基本操作实现===============
    //1.初始化
    void InitStack(SqStack& S) {
        S.top = -1;
    }
    //2.判栈空
    bool StackIsEmpty(SqStack S) {
        if (S.top == -1)
            return true;
        else
            return false;
    }
    //3.进栈
    bool Push(SqStack& S, ElemType x) {
        //如果判断栈是否满了
        if (S.top == MaxSize - 1)
            return false;
        S.data[++S.top] = x;//这是栈顶从-1开始的情形。所以栈顶先加1再进栈
        //S.data[S.top++] = x;//这是栈顶从0开始的情形。所以先进栈,然后再栈顶加1
        return true;
    }
    //4.出栈
    bool Pop(SqStack& S, ElemType& x) {
        //判断栈是否为空
        if (S.top == -1)
            return false;
        x = S.data[S.top--];//这是栈顶从-1开始的情形。所以先出栈再指针减一
        //x = S.data[--S.top];//这是栈顶从0开始的情形。所以先栈顶指针减一再出栈
    }
    //5.读栈顶元素,将读取的结果放在x中
    bool GetTop(SqStack S, ElemType& x) {
        //如果栈为空,
        if (S.top == -1)
            return false;
        x = S.data[S.top];
        return true;
    }
  • 相关阅读:
    js 提示框的实现---组件开发之(一)
    js 原型链
    js 哈希路由原理实现
    js 弹窗的实现
    js 滑动门的实现
    Delphi IDFtp用法,包含断点续传
    memortstream Base64编码和filestream base64编码不同
    Delphi另一个多线程函数:BeginThread用法
    delphi 讲的比较详细的多线程(推荐)
    多线程简单实用
  • 原文地址:https://www.cnblogs.com/hidamowang/p/11838652.html
Copyright © 2020-2023  润新知