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

    这个作业属于哪个班级 数据结构--网络2011/2012
    这个作业的地址 DS博客作业02--栈和队列
    这个作业的目标 学习栈和队列的结构设计及运算操作
    姓名 郑俊佳

    0.PTA得分截图

    1.本周学习总结(0-5分)

    1.1 栈

    画一个栈的图形,介绍如下内容。
    栈的定义:栈是一种只能在一端进行插入或删除操作的线性表。栈又称为后进先出的线性表,其中有几个名词:栈顶、栈底、空栈。
    栈顶:允许插入和删除的一端。
    栈底:不允许插入和删除的一端。
    空栈:表中没有元素。

    进栈出栈规则:
    栈顶出栈->栈底最后出栈;
    时进时出->元素未完全进栈时,即可出栈。
    顺序栈的结构、操作函数

    顺序栈定义结构体:

    typedef struct
    {
      ElemType data[MaxSize];  //存放栈中的数据元素
      int top;                 //栈顶指针,即存放栈顶元素在data数组中的下标
    }SqStack;                  //顺序栈的类型
    

    初始化顺序栈:

    void InitStack(SqStack *&s)
    {
      s=new SqStack;   //分配一个顺序栈空间,首地址存放在s中
      s->top=-1;       //栈顶指针置为-1,即栈空
    }
    

    销毁顺序栈:

    void DestroyStack(SqStack *&s)
    {
      free(s);
    }
    

    判断顺序栈是否为空:

    bool StackEmpty(SqStack * s)
    {
      return(s->top==-1);
    }
    

    元素进入顺序栈:

    bool Push(SqStack *&s,ElemType e)
    {
       if(s->top==MaxSize-1)   //栈满情况,即栈上溢出
            return false;
       s->top++;              //栈顶指针增1
       s->data[s->top]=e;     //元素e放在栈顶指针处
       return true;
    }
    

    元素出顺序栈:

    bool Pop(SqStack *&s,ElemType &e)
    {
      if(s->top==-1)     //栈为空的情况,即栈下溢出
         return false;
      e=s->data[s->top]; //取出栈顶元素
      s->top--;          //栈顶指针减1
      return true;
    }
    

    取顺序栈中栈顶元素:

    bool GetTop(SqStack *&s,ElemType &e)
    {
       if(s->top==-1)    //栈为空的情况,即栈下溢出
           return false;
       e=s->data[s->top];  //取栈顶元素
       return true;
    }
    

    共享栈:合并两个栈,用一个数组实现两个栈。

    共享栈四要素:
    栈空条件:栈1空为top1==-1;栈2空为top2==MaxSize。
    栈满条件:top1==top2-1;
    元素x进栈操作:进栈1操作为top1++;data[top1]=x;进栈2操作为top2--;data[top2]=x。
    出栈x操作:出栈1操作为x=data[top1];top1--;出栈2操作为x=data[top2];top2++。
    共享栈结构体:

    typedef struct
    {
      ElemType data[MaxSize]; //存放共享栈中的元素
      int top1,top2;          //两个栈的栈顶指针
    }DStack;                  //共享栈的类型
    

    链栈的结构、操作函数

    链栈的结构体:

    typedef struct linknode
    {
       ElemType data;         //数据域
       struct linknode *next; //指针域
    }LinkStNode;              //链栈结点类型
    

    初始化链栈:

    void InitStack(LinkStNode *&s)
    {
       s=new LinkStNode;
       s->next=NULL; //栈空
    }
    

    销毁链栈:

    void DestroyStack(LinkStNode *&s)
    {
       LinkStNode * pre=s,*p=s->next; //pre指向头结点,p指向首结点
       while(p!=NULL)                 //循环到p为空
        {
          free(pre);                  //释放pre结点
          pre=p;                      //pre、p同步后移
          p=pre->next;                
        }
        free(pre);                   //此时pre指向尾结点,释放其空间
    }
    

    判断链栈是否为空:

    bool StackEmpty(LinkStNode *s)
    {
        return (s->next=NULL);
    }
    

    元素进入链栈:

    void Push(LinkStNode *&s,ElemType e)
    {
       LinkStNode *p;    
       p=new LinkStNode; //新建结点p
       p->data=e;        //存放元素e
       p->next=s->next;  //将p结点插入作为首结点
       s->next=p;
    }
    

    元素出链栈:

    bool Pop(LinkStNode *&s,ElemType &e)
    {
       LinkStNode * p;
       if(s->next==NULL)  //栈空情况
           return false;
       p=s->next;        //p指向首结点
       e=p->data;        //提取首结点值
       s->next=p->next;  //删除首结点
       free(p);          //释放被删除结点的存储空间
       return true;
    }
    

    取链栈栈顶元素:

    bool GetTop(LinkStNode *&s,ElemType &e)
    {
       if(s->next==NULL) //栈空情况
          return false;
       e=s->next->data; //提取其首结点值
       return true; 
    }
    

    1.2 栈的应用

    问题:
    exp="1+2(4+12)";
    做法:
    1.转后缀表达式
    2.后缀表达式求值
    中缀表达式:运算符号位于两个运算数之间。如:a+b
    c-d/e
    后缀表达式:运算符号位于两个运算数之后。如:abc*+de/-

    将算式exp转化成后缀表达式postexp:

    void trans(char * exp,char postexp[])
    {
       cahr e;
       SqStack * Optr;
       InitStack(Optr);
       int i=0;
       while(*exp!='')
        {
          switch(*exp)
           {
             case '(':
                  Push(Optr,'(');
                  exp++;
                  break;
             case ')':
                  Pop(Optr,e);
                  while(e!='(')
                   {
                     postexp[i++]=e;
                     Pop(Optr,e);
                   }
                   exp++;
                   break;
            case '+':
            case '-':
                 while(!StackEmpty(Optr))
                  {
                    GetTop(Optr,e);
                    if(e!='(')
                     {
                       postexp[i++]=e;
                       Pop(Optr,e);
                     }
                    else
                       break;
                  }
                 Push(Optr,*exp);
                 exp++;
                 break;
            case '*':
            case '/':
                 while(!StackEmpty(Optr))
                    {
                      GetTop(Optr,e);
                      if(e=='*'||e=='/')
                        {
                          postexp[i++]=e;
                          Pop(Optr,e);
                        }
                      else
                         break;
                    }
                Push(Optr,*exp);
                exp++;
                break;
            default:
                 while(*exp>='0'&&*exp<='9')
                    {
                      postexp[i++]=*exp;
                      exp++;
                    }
                    postexp[i++]='#';
           }
        } 
        while(!StackEmpty(Optr))
           {
             Pop(Optr,e);
             postexp[i++]=e;
           }
           postexp[i]='';
           DestroyStack(Optr);
    }
    

    1.3 队列

    画一个队列的图形,介绍如下内容。

    顺序队列的结构、操作函数

    顺序队列的结构体:

    typedef struct
    {
      ElemType data[MaxSize]; //存放队中的元素
      int front,rear;         //队头和队尾指针
    }SqQueue;                 //顺序队类型
    

    初始化顺序队列:

    {
      q=new SqQueue;
      q->front=q->rear=-1;
    }
    

    销毁顺序队列:

    void DestroyQueue(SqQueue *&q)
    {
      free(q);
    }
    

    判断顺序队列是否为空:

    bool QueueEmpty(SqQueue *q)
    {
      return (q->front==q->rear);
    }
    

    元素进入顺序队列:

    bool enQueue(SqQueue *&q,ElemType e)
    {
      if(q->rear==MaxSize-1)  //队列满上溢出
         return false;
      q->rear++;             //队尾增1
      q->data[q->rear]=e;    //rear位置插入元素e
      return true;
    }
    

    元素出顺序队列:

    bool deQueue(SqQueue *&q,ElemType &e)
    {
       if(q->front==q->rear)   //队列空下溢出
          return false;
       q->front++;             //队头增1
       e=q->data[q->front];    //front位置出队列
       return true;
    }
    

    环形队列的结构、操作函数

    初始化环形队列:

    void InitQueue(SqQueue *&q)
    {
      q=new SqQueue;
      q->front=q->rear=0;
    }
    

    销毁环形队列:

    void DestroyQueue(SqQueue *&q)
    {
       free(q);
    }
    

    判断队列是否为空:

    bool QueueEmpty(SqQueue *q)
    {
       return (q->front==q->rear);
    }
    

    元素进入环形队列:

    bool enQueue(SqQueue *&q,ElemType e)
    {
       if((q->rear+1)%MaxSize==q->front) //队列满上溢出
          return false;
       q->rear=(q->rear+1)%MaxSize;     
       q->data[q->rear]=e;
       return true;
    }
    

    元素出环形队列:

    bool deQueue(SqQueue *&q,ElemType &e)
    {
        if(q->front==q->rear)          //队列空下溢出
           return false;
        q->front=(q->front+1)%MaxSize;
        e=q->data[q->front];
        return true;
    }
    

    链队列的结构、操作函数

    链队列的结构体:

    typedef struct qnode
    {
      ElemType data;     //存放元素
      struct qnode *next;//下一个结点指针
    }DataNode;           //链队数据结点的类型
    

    链队头结点类型LinkQuNode:

    typedef struct
    {
      DataNode *front; //指向队首结点
      DataNode *rear;  //指向对尾结点
    }LinkQuNode;       //链队结点的类型
    

    初始化链队:

    void InitQueue(LinkQuNode *&q)
    {
         q=new LinkQuNode;
         q->front=q->rear=NULL;
    }
    

    销毁链队:

    void DestroyQueue(LinkQuNode *&q)
    {
         DataNode *pre=q->front,*p;  //pre指向队首结点
         if(pre!=NULL)
           {
             p=pre->next;           //p指向结点pre的后续结点
             while(p!=NULL)         //p不为空时循环
                  {
                    free(pre);     //释放pre结点
                    pre=p;         //pre后移
                    p=p->next;     //p后移
                  }
             free(pre);            //释放最后一个数据结点
          }
         free(q);                 //释放链队结点
    }
    

    判断链队是否为空:

    bool QueueEmpty(LinkQuNode *q)
    {
         return (q->rear==NULL);
    }
    

    元素进入链队:

    void enQueue(LinkQuNode *&q,ElemType e)
    {
        DataNode *p;
        p=new DataNode;        //创建新结点
        p->data=e;
        p->next=NULL;
        if(q->rear==NULL)      //若链队为空,则新结点既是队首结点又是对尾结点
           q->front=q->rear=p;
        else                  //若链队不空
       {
            q->rear->next=p;  //将结点p链到对尾,并将rear指向它
            q->rear=p;
       }
    }
    

    元素出链队:

    bool deQueue(LinkQuNode *&q,ElemType &e)
    {
         DataNode *t;
         if(q->rear==NULL)          //原来队列为空
            return false;
         t=q->front;                //t指向首结点
         if(q->front==q->rear)      //原来队列只有一个数据结点时
            q->front=q->rear=NULL;
         else                       //原来队列中有两个或两个以上结点时
            q->front=q->front->next;
         e=t->data;
         free(t);
         return true;
    }
    

    队列应用,要有具体代码操作。

    2.PTA实验作业(4分)

    此处请放置下面2题代码所在码云地址(markdown插入代码所在的链接)。如何上传VS代码到码云

    2.1 符号配对

    2.1.1 解题思路及伪代码

    解题思路:定义flag进行判断操作,输入左符号时入栈,输入右符号时并且判断栈里面是否有元素,若无则为一种情况,若有则进行配对,判断是否是该右符号对应的左符号,用flag标记对应的情况。
    伪代码:

    int flag=0;
    for (遍历条件)
    {
    	if (为左符号)
    	{
    		入栈;
    	}
    	else if (栈为空且有右符号)
    	{
    		flag = 1;
    		break;
    	}
    	else if (各自左符号与右符号配对情况)
    	{
    		出栈;
    	}
    }
    if (flag == 1)
    {
    	右符号剩余;
    }
    else if (栈为空)
    {
    	匹配;
    }
    else
    {
    	正常情况的不匹配;
    }
    

    2.1.2 总结解题所用的知识点

      • 宏定义,结构体,函数分装等
      • 申请空间用malloc动态申请。
      • 使用了链的存储功能,并且还使用了静态字符数组定义。

    2.2 银行业务队列简单模拟

    2.2.1 解题思路及伪代码

    解题思路:
    先判断编号的奇偶,若为奇数进A队列,若为偶数进B队列,再分别计算A队列和B队列的元素个数,后判断A无元素和只有1个元素的特殊情况,两种情况下再判断B的个数,之后普通情况,另A的元素个数除以2,因为2人为一组,1组输出2个编号后B输出1个编号,但要考虑到A的元素个数为奇数个,故要添加判断,若其为奇数最后一组输出1个。
    伪代码:

    for (遍历条件)
    {
    	if (编号为奇数)
    	{
    		进A;
    	}
    	else
    	{
    		进B;
    	}	
    }
    统计A和B的个数
    if (A个数为0)
    {
    	全部输出B元素;
    }
    else if (A元素个数为1)
    {
    	输出A;
    	全部输出B;
    }
    else
    {
    	int i = A个数 / 2;
    	for (n = 1; n <= i; n++)
    	{
    		if (n < i)
    		{
    			输出A2个元素;
    		}
    		else if (n == i && A个数为奇数)
    		{
    			输出A1个元元素;
    		}
    		else if (n == i && A个数为偶数)
    		{
    			输出A2个元素;
    		}
    		if (B还有元素)
    		{
    			输出B1个元素;
    		}
    	}
    }
    

    2.2.2 总结解题所用的知识点

      • queue相关函数的使用
      • 队列优先输出的顺序
      • 本题需要考虑A对列的特殊情况,考虑其个数以及奇偶性。

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

    找1份优秀代码,理解代码功能,并讲出你所选代码优点及可以学习地方。主要找以下类型代码:

    考研题
    ACM题解
    leecode--栈
    leecode--队列
    注意:不能选教师布置在PTA的题目。完成内容如下。

    3.1 题目及解题代码

    可截图,或复制代码,需要用代码符号渲染。

    3.2 该题的设计思路及伪代码

    链表题目,请用图形方式展示解决方法。同时分析该题的算法时间复杂度和空间复杂度。

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

  • 相关阅读:
    React 懒加载组件
    按键精灵Q语言基础
    zookeeper安装和配置(单机+伪集群+集群)
    hbase-site.xml 配置详解
    MySQL主从复制与读写分离概念及架构分析
    mysql 主从复制原理
    Struts2教程
    广告点击率预测(CTR) —— 在线学习算法FTRL的应用
    搭建git服务器
    git常用命令
  • 原文地址:https://www.cnblogs.com/jioky/p/14616802.html
Copyright © 2011-2022 走看看