zoukankan      html  css  js  c++  java
  • DS博客作业02--栈和队列

    0.PTA得分截图

    1.本周学习总结

    1.1 总结栈和队列内容

    栈的存储结构及操作

    顺序栈:

    链栈:

    //顺序栈的结构体
    typedef struct 
    {
        int data[MaxSize];
        int top;
    }Stack;
    tpyedef Stack *SqStack;
    
    //链栈结构体
    typedef struct Node
    {
        char data;
        struct Node *next; 
    } Node, *ListStack;
    
    //顺序栈初始化
    void InitStack (SqStack &S)
    {
        S=new Stack;
        S->top=-1;
    }
    
    //链栈初始化
    void InitStack (ListStack &S)
    {
        S=new Node;
        S->next=NULL;
    }
    
    //顺序栈入栈
    bool Push(SqStack &S,int e)
    {
        if(栈满)return false;
        栈顶指针增1;
        元素e放在栈顶指针处;
    }
    
    //链栈入栈
    void Push(LinkStack &S,int e)
    {
        //链栈不考虑栈满
        新增结点p存放元素e;
        采用头插法将p结点插入;
    }
    
    //顺序栈出栈
    bool Pop(SqStack &S,int &e)
    {
        if(栈空)return false;
        取栈顶元素;
        栈顶指针减1;
    }
    
    //链栈出栈
    bool Pop(LinkStack &S,int &e)
    {
        if(栈空)return false;
        p指向头结点后一个元素;
        e存放该元素的值;
        删除该元素;
    }
    
    //顺序栈销毁
    void DestroyStack(SqStack &S)
    {
        delete S;
    }
    
    //链栈销毁
    void DestroyStack(LinkStack &S)
    {
        //链栈销毁涉及删除链的操作
        while(遍历链栈)
        {
            p=S->next;
            delete S;
            S=p;
        }
    }
    
    //C++模板类
    stack <int> S;     //初始化链栈
    S.push(x);    //元素x进栈
    S.top();    //返回栈顶元素
    S.pop();    //出栈;
    S.empty();    //判断栈空,若空返回true
    S.size();    //访问栈中元素个数
    

    栈的应用

    1.判断对称串

    定义顺序栈;
    将字符串入栈;
    for(遍历字符串)
    {
        出栈元素e;
        if(e!=当前串字符)
        {
            return false;
        }
        return true;
    }
    

    2.括号匹配

    定义顺序栈;
    while(遍历串)
    {
       if(不是括号) 取下一个字符;
       else
       {
           if(左括号) 入栈;
           else if(右括号)
           {
                if(空栈)错误;
                if(匹配)出栈;
                else 错误;           
           }
        }   
    ) 
    if (栈依然为空) 
        匹配正确;
    else   
        错误;
    

    3.中缀表达式转后缀表达式

    定义栈;
    输入字符串s;
    for(遍历字符串)
    {
        if(是数字、小数点、正负号)
        {
            输出,并判断下一个是否是数字或小数点;//若不是,则输出空格隔开两个数字
    	continue;
        }
        if(出现右括号)
        {
            出栈输出,直到遇到左括号或栈空;
    	continue;
        }
        if(栈空或者比栈顶符号优先级高)
        {
    	入栈;
        }
        else
        {
    	先出栈直到遇到左括号或者栈空,再入栈新符号;
        }
    }
    while(栈不空)
    {
        出栈栈中剩余符号;
    }
    

    4.迷宫路径

    将入口进栈;
    mg[xi][yi]=-1;
    while(栈不空)
    {
        取栈顶方块;
        if(当前方块是出口)
        {
            输出路径;
            return true;
        }
        查找下一可走方块;
        if(找到相邻可走方块)
        {
            当前方块的坐标和方位进栈;
            mg[i][j]=-1;
        }
        if(没有找到相邻可走方块)
        {
            出栈方块;
            mg[i][j]=0;
        }
    }
    return false;
    

    队列的存储结构及操作

    顺序队:

    链队:

    //顺序队结构体定义
    typedef struct 
    {
        int data[MaxSize];
        int front,rear;
    }queue;
    typedef queue *SqQueue;
    
    //链队结构体定义
    typedef struct qnode
    {
        int data;
        struct qnode *next;
    }QNode,*QueuePtr;
    
    typedef struct
    {
        QueuePtr front;
        QueuePtr rear;
    }LinkQueue;
    
    //顺序队初始化
    void InitQueue(SqQueue &q)
    {
        q=new queue;
        q->front=q->rear=-1;
    }
    
    //链队初始化
    void InitQueue(LinkQueue &q)
    {
       q.front=q.rear=new QNode;
       q.front->next=NULL;
    }
    
    //顺序队入队
    bool enQueue(SqQueue &q, int e)
    {
        if(队满)    return false;
        队尾增1;
        rear位置插入元素e;
    }
    
    //链队入队
    void enQueue(LinkQueue &q, int e)
    {
        //不需要考虑队满
        新建结点p;
        e赋值给结点p;
        尾插法插入结点p;
    }    
    
    //顺序队出队
    bool deQueue(SqQueue &q, int &e)
    {
        if(队空) return false;
        队头增1;
        取对头元素赋值给e;
    }
    
    //链队出队
    bool deQueue(LinkQueue &q, int &e)
    {
        if(队空) return false;
        p指针指向队头后一个结点;
        取p结点元素赋值给e;
        删除结点p;
        if(队尾为p) q.rear=q.front;//只剩一个数据结点
        delete p;
    }
    
    //顺序队销毁
    void DestroyQueue(SqQueue &q)
    {
        delete q;
    }
    
    //链队销毁
    void DestroyQueue(LinkQueue &q)
    {
        while(q.front)
        {
            q.rear=q.front->next;
            delete q.front;
            q.front=q.rear;
        }
    }
    
    //C++模板类
    queue<int>q//初始化链队
    q.push(e)    //元素e入队
    q.front()    //访问队头元素
    q.rear()    //访问队尾元素
    q.pop()    //出队
    q.empty()     //判断队列是否为空,为空返回true
    q.size()    //访问队列长度
    
    //循环队列初始化
    q->front=q->rear=0;
    
    //循环队列为空
    q->front=q->rear;
    
    //循环队列队满
    (q->rear+1) % MaxSize=q->front;
    
    //循环队列进队
    q->rear=(q->rear+1) % MaxSize;
    
    //循环队列出队
    q->front=(q->front+1) % MaxSize;
    

    队列应用

    1.报数游戏(1出列 2站右)

    n个人入队;
    while(队列不空)
    {
        出队一个元素e;
        if(队列不空)
        {
            出队一个元素e;
            刚出队的元素e再入队;
        }
    }
    

    2.迷宫路径

    将入口入队;
    mg[xi][yi]=-1;
    while(队列q不空)
    {
        出队方块e;
        if(e是出口) 
        {
            输出路径;
            return true;
        }
        for(对于方块e的所有可走方块e1)
        {
            将方块e1进队;
            mg[i][j]=-1;
        }
    }
    return false;
    

    3.各类排队问题,如银行排队,舞会舞伴等。

    1.2.谈谈你对栈和队列的认识及学习体会。

    • 栈与队列是操作受限的线性表,栈只能从栈顶插入删除,栈是先进后出,队列只允许在表的一端插入,另一端删除元素,队列是先进先出。
    • 栈的优点:在需要按照保存数据的相反的顺序来使用数据时,就可以用到栈。比如:递归算法,递归算法用到的保存足迹和返回运算就是要靠栈来实现,逆序输出等。
    • 队列的优点:排队的应用,在模拟队列上的应用。
    • 顺序栈和链栈:顺序栈出栈不删除数据元素,链栈出栈是物理删除数据元素。顺序栈需要考虑栈满,链队则不需要考虑。链栈可以使用C++模板类。
    • 顺序队和链队:大体上与顺序栈和链栈相似,个别插入删除元素函数稍有不同。

    2.PTA实验作业

    2.1.题目1:表达式转换

    2.1.1代码截图

    2.1.2本题PTA提交列表说明。

    1.编译错误:编译器未选择C++。

    2.2 题目2:符号匹配

    2.2.1代码截图

    2.2.2本题PTA提交列表说明。

    1.部分正确:缺右边情况答案错误。解决方法:在最后栈不空判断加入e = St.top();right = 1;
    因为输入连续左括号时,如(((((,也是缺右边的一种情况。
    2.部分正确:缺右边情况仍然错误。解决方法:栈不空且不匹配条件下加入语句e = St.top();
    right = 1;因为出现不匹配,如[ ( ] ),也是符号’(‘缺右边的一种情况。
    3.部分正确:数组b遍历到’/’或’/’时,造成当出现//,’’号被算两次,结果答案错误。解决方法:将两个if条件判断语句改成if ,else if语句防止第二个if条件成立。

    3.阅读代码(0--4分)

    3.1 题目及解题代码

    3.1.1 该题的设计思路

    建立一个临时的容器,模拟弹出过程,如果这个弹出的数字和栈顶数字是吻合的,那么栈就要把已有的数字弹出来。如果栈是空的,或者栈顶数字和弹出的数字不等,那么我们应该把pushed数字一直往里放,直到相等为止。如果临时容器最后是空,返回true;否则,返回false。

    3.1.2 该题的伪代码

    for i=0 to len do
    {
        if(popped的元素等于res的元素)
            弹出res元素;
        else 
        {
            while(两个元素不相等)
            {
                pushed元素放入res中;
            }
        }
    }
    

    3.1.3 运行结果

    3.1.4分析该题目解题优势及难点。

    • 题中使用vector建立一个临时的容器,模拟题目的入栈出栈操作,没有新建栈进行模拟。
    • popped序列可能是随机的,第一个入栈元素可能在中途出栈,所以需要储存pushed序列,直到与popped元素相等出栈。
    • 如何表示和保存入栈和出栈序列是题目的关键。

    3.2 题目及解题代码

    3.2.1 该题的设计思路

    先将输入的原始队列按照身高h递减、若h相同则以k递增的规则进行排序。然后从前往后遍历扫描一遍队列,并依据k进行插入。
    递减h、递增k排列:

    3.2.2 该题的伪代码

    升高h降序排列;
    if(h相等)  
        k升序排列;
    while(遍历数组)
    {
        按k排列每个人位置;
    }
    

    3.2.3 运行结果

    3.2.4分析该题目解题优势及难点。

    • 题目巧妙的按照递减h为主次序,递增k为赋次序进行排序,之后只需要遍历数组对每个k的值排列。
    • 先安排个子高的人,再安排个子矮的人,因为个子矮的人的插入不会对个子高的人的排序产生影响。
    • 首先要理解题目的意思,理解k的含义,确定如何排序才能使k的序列正确且不被其他元素插入而破坏。
  • 相关阅读:
    【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
    【CF600E】Lomsat gelral(dsu on tree)
    【Vijos】lxhgww的奇思妙想(长链剖分)
    【HDOJ6586】String(枚举)
    【HDOJ6578】Blank(DP)
    【HDOJ6583】Typewriter(SAM,DP)
    JAVA 集合 List 分组的两种方法
    HashMap的实现原理
    HashMap, HashTable, CurrentHashMap的区别
    java ThreadLocal(应用场景及使用方式及原理)
  • 原文地址:https://www.cnblogs.com/c4412/p/12524245.html
Copyright © 2011-2022 走看看