zoukankan      html  css  js  c++  java
  • 栈和队列

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

    0.PTA得分截图

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

    1.1 栈

    栈的定义以及特点

    • 栈是一种只能在一端进行插入和删除操作的线性表,表中允许进行插入和删除的一端为栈顶,另一端为栈底。
    • 当栈中没有数据元素时称为空栈。
    • 栈的插入操作称为入栈或者进栈,栈的删除操作称为出栈或者退栈。
    • 栈的主要特点为后进先出,每次出栈的元素都为当前栈的栈顶元素。

    顺序栈的结构

    • 栈的代码定义
    typedef struct {
    	ElemType data[MaxSize];//存放元素
    	int top=-1;//栈顶指针,下标
    }SqStack;//顺序栈的类型
    

    栈的存储和删除通过top的移动进行元素的进入和删除,对栈的元素进行删除实际上元素仍然在栈里面,仅是移动指针的位置。

    顺序栈操作函数

    • 栈空栈满的判断条件(进行插入删除时需要注意的条件)
      若初始时s->top定义为-1,则栈空的条件为s->top=-1,栈满的条件为s->top=MaxSize-1(MaxSize为数组最大下标)。
    • 初始化栈
    void InitStack(S)
    {
       s=new Stack;//动态申请内存
       s->top=-1;
    }
    
    • 进栈
    bool Push(SqStack &S,ElemType e)
    {
        if(s->top==MaxSize-1)//顺序栈进栈时要注意栈是否已满
        {
            return false;
        }
        s->top++;//栈顶指针加1
        s->data[s->top]=e; 
        return true;
    }
    

    进行是否栈满的判断,栈顶指针加一,放入元素

    • 出栈
    bool Pop(SqStack &s,ElemType &e)
    {
        if(s->top==-1)//顺序栈出栈时要注意栈是否为空
        {
           return flase
        }
        e=s->data[s->top];
        s->top--;//栈顶指针减一
        return ture;
    }
    

    进行是否栈空的判断,栈顶指针减一,移除元素

    • 取栈顶元素
    bool GetTop(SqStack *s,ElemType &e)
    {
       if(s->top==-1)//判断是否为空
       return false;
       e=s->data[s->top];
       return true;
    }
    

    进行是否栈空的判断,取栈顶指针位置,输出元素

    链栈的结构

    • 栈的代码定义
    typedef struct linknode
    {
       ElemType data;//数据域
       struct linknode *next;//指针域
    }LinkStNode;//类型
    

    通过对指针的结点移动进行数据的插入和输出。

    链栈的操作函数

    • 栈空栈满的判断条件(区别于顺序栈)
      栈空的判断条件为s->next=NULL,一般不用判断栈满,只有内存溢出时才栈满。
    • 初始化栈
    void InitStack(LiStack &s)
    {
       s=new LiNode;//动态申请内存
       s->next=NULL;
    }
    
    • 进栈
    void Push(LiStack &s,Elemtype e)
    {
       LiStack p;
       p=new LiNode;//新建结点进行插入
       p->data=e;//头插法
       p->next=s->next;
       s->next=p;
    }
    

    进栈一般不用判断栈满,利用头插法进行元素的进栈

    • 出栈
    bool Pop(LiStack &s,ElemType &e)
    {
       LiStack p;//新建结点临时保存
       if(s->next=NULL)
       {
          return false;
       }
       p=s->next;
       e=p->data;
       s->enxt=p->next;//改变结点指向
       delete p;//删除
       return true;
    }
    

    出栈时需要对栈空进行判断,后利用链表删除某一结点的数据方法,新建临时结点保存需要删除的结点,后改变前继结点的指向,物理删除需要删除的结点。

    c++模板类:stack

    • stack <元素类型> s:初始化栈
    • s.push(t):将元素t入栈
    • s.pop():出栈顶元素
    • s.top():返回栈顶元素
    • s.empty():当栈为空时返回true
    • s.size():访问栈的元素个数

    1.2 栈的应用

    表达式

    • 中缀表达式:运算符号位于两个运算数之间。后缀表达式:运算符号位于两个运算数之后。
    • 中缀表达式转为后缀表达式:
      建立一个栈用于存放运算符,每个运算符号进栈时都要比较一下其和栈顶的的符号优先级大小,若优先级较低,则栈里面的运算符需要出来,其进栈,当操作结束后,需要观察栈里面是否还有运算符,若有则需要将其出栈,若遇到括号,由于括号的优先级最高,当符号配对成功时,需要出栈的元素。
      例:

    (1)将中缀表达式a+b * c+(d * e+f) * g转为后缀表达式,当读入f时栈里面的内容为+(+
    解析:+进栈, * 进栈,+优先级较低,故出* 和 +,+进栈,(进栈, * 进栈,+优先级较低,故*出栈,+进栈,此时栈里面剩余+(+。

    (2)将表达式a * (b+c)-d转为后缀表达式abc+ * d-。
    解析: * 进栈,(进栈,+进栈,)进栈,配对成功,+出栈, * 出栈,-进栈,完成操作后,-还在栈里,-出栈。

    1.3 队列

    队列的定义以及特点

    • 队列是一种操作受限的线性表,仅允许在表的一端进行插入操作,在表的另一端进行删除操作。
    • 把进行删除的一端称为队头或队首,进行插入的一端称为队尾。
    • 插入新元素,新元素进队后为新的队尾元素,元素出队后,其后继的元素称为队头元素。
    • 队的特点为先进先出

    顺序队列的结构

    • 队列的代码定义
    typedef struct
    {
       ElemType data[MaxSize];
       int front,rear;//队首,队尾指针
    }Queue;
    

    通过队首队尾指针的移动进行元素的插入和删除,front指向队头元素,rear指向队尾元素。

    顺序队列的操作函数

    • 队列空满的判断条件(进行插入删除时需要注意的条件)
      初始定义front和rear为-1,对空的条件为front=rear,队满的条件为rear=MaxSize。
    • 初始化队列
    void InitQueue(Queue &q)
    {
       q=new Queue;//动态申请内存
       q->front=q->rear=-1;
    }
    
    • 进队列
    bool enQueue(SqQueue &q,ElemType e)
    {
        if(q->rear+1==MaxSize)//判断是否栈满
        return flase;
        q->rear=q->rear+1;//移动指针
        q->data[q->rear]=e;
        return ture;
    }
    

    跟顺序栈的进栈一样,顺序队列的进队需要判断rear的下一位是否已满,若未满即可移动指针插入元素。

    • 出队列
    bool deQueue(SqQueue &q,Elemtype &e)
    {
       if(q->front==q->rear)//判断队是否为空
       return flase;
       e=q->data[q->front];
       q->front=q->front+1;//移动指针
       return ture;
    }
    

    顺序队列得到进队需要判断队列是否为空,后移动front到下一位,进行出队操作。

    环形队列的结构
    由于顺序队列的队满条件为rear=MaxSize-1,当满足这一条件时,即跳出操作,但此时可能仍有若干空位置,这种情况为假溢出。
    为更好利用存储空间,可构建一个环形队列。

    • 队列的代码定义
       typedef struct
    {
       ElemType data[MaxSize];
       int front,rear;//队首,队尾指针
    }Queue;
    

    环形队列的操作函数

    • 队头指针front循环增1:front=(front+1)%MaxSize,队尾指针rear循环增1:rear=(rear+1)%MaxSize
    • 队满的判定条件:(q->rear+1)%MaxSize=q->front,队空的判定条件:q->front=q->rear。
    • 初始化队列
    void InitQueue(SqQueue &q)
    {
       q=new Queue;//动态申请内存
       q->front=q->rear=0;
    }
    

    通过分别移动front和rear进行进队列和出队列操作。

    • 进环形队列
    bool enQueue(SqQueue &q,Elemtype e)
    {
       if((q->rear+1)%MaxSize==q->front)//判断是否队满
       return false;
       q->rear=(q->rear+1)%MaxSize;//移动rear
       q->data[q->rear]=e;
       return true;
    }
    

    进队列需要判断是否队满,判断(q->rear+1)%MaxSize是否等于q->front,后移动rear指针,q->rear=(q->rear+1)%MaxSize。

    • 出环形队列
    bool deQueue(SqQueue &q,Elemtype e)
    {
       if(q->front==q->rear)//判断是否队空
       return false
       e=q->data[q->front];
       q->front=(q->front+1)%MaxSize;//移动front
       return true;
    }
    出队需要判断是否对空,判断q->front==q->rea,后移动front指针q->front=(q->front+1)%MaxSize。
    

    链队列的结构

    • 队列的代码定义
    typedef struct
    {
       QNode *front;
       QNode *rear;
    }LinkQueue;
    

    通过移动front和rear实现进栈和出栈

    链队列的操作函数

    • 队空的判断条件为front=rear=NULL,一般不用考虑队满
    • 初始化链队列
    void InitQueue(LinkQuNode &q)
    {
       q=new LinkQuNode;
       q->front=q->rear=NULL;
    }
    
    • 进队列
    bool enQueue(LinkQuNode &q,ElemType e)
    {
       p=new QNode;
       p->data=e;//新建结点
       p->next=NULL;//避免后面无结束
       q->rear->next=p;
       q->rear=p;//尾指针移动
    }
    

    进队列不需要判断队满,利用尾插法插入,并且改变rear的指向。

    • 出队列
    bool deQueue(LinkQuNode &q,ElemType e)
    {
        Node t;
        if(q->rear==NULL)
        return false;
        t=q->front;
        if(q->front==q->rear)//此时只有一个数据
        {
           q->front=q->rear=NULL;
        }
        else
        {
           q->front=q->front->next;//移动front
        }
        e=t->data;
        delete t;//删除
    }
    

    出队列判断是否为空,并考虑是否只有一个数据,移动front。

    队列应用
    例题:

    #include <iostream>
    #include <queue>
    using namespace std;
    int main()
    {
    	int m;//人数
    	int n;//数字
    	queue <int>person;
    	cin >> m >> n;
    	if (n > m)//特殊情况
    	{
    		printf("error!");
    	}
    	else
    	{
    		int i ;
    		for (i = 1; i <= m; i++)//进入队列
    		{
    			person.push(i);
    		}
    		int flag = 1;//控制空格
    		int num;
    		 i = 0;
    		while (!person.empty())
    		{
    			i++;
    			if (i%n == 0)
    			{
    				num = person.front();
    				if (flag == 1)
    				{
    					flag = 0;
    					cout << num;
    				}
    				else
    				{
    					cout << ' ' << num;
    				}
    				person.pop();//出队列
    				i = 0;//重新计数
    			}
    			else
    			{
    				num = person.front();
    				person.push(num);//进队列
    				person.pop();//出队列
    			}
    		}
    	}
    	return 0;
    }
    

    对于此类的报数问题还有搜索迷宫路径问题,可用队列解决,题中不满足报数条件的单位需要进行出队再入队的操作,具体的要求根据题意改变。

    c++模板类:queue

    • q.push():入队
    • q.pop():出队
    • q.front():取队头元素
    • q.back():取队尾元素
    • q.empty():队是否为空

    2.PTA实验作业(4分)

    7-2 符号配对地址
    7-6 银行业务队列简单模拟地址

    7-2 符号配对

    解题思路及伪代码

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

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

    总结解题所用的知识点

    stack相关函数的应用、flag标记情况、情况不同的判断考虑,本题需要考虑到左符号剩余,右符号剩余,配对情况,不配对情况,需要多重if 来进行约束判断,最后根据flag的值输出对应的结果。

    7-6银行业务队列简单模拟

    解题思路及伪代码

    解题思路:
    先判断编号的奇偶,若为奇数进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个元素;
    		}
    	}
    }
    

    总结解题所用的知识点

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

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

    3.1 题目及解题代码

    代码:

     bool validateStackSequences(vector<int>& pushed, vector<int>& popped) 
    {
            stack<int> story;
            int j=0;//popped的index
            for(int i=0;i<pushed.size();++i)
            {
                story.push(pushed[i]);
                while(!story.empty()&&story.top()==popped[j])//出与入相同时执行pop
                {
                    story.pop();
                    j++;
                }
            }
            
            while(!story.empty()&&j<popped.size())
            {
                if(story.top()==popped[j])//为pop首元素时执行pop
                {
                    story.pop();
                    j++;
                }
                else
                {
                    return false;
                }
            }
            return true;
            
        }
    

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

    伪代码:

    for(遍历条件)
    {
        push入新栈;
        while(栈顶与pop的top一样时)
        {
           执行pop;
        }
    }
    while(新栈不为空)
    {
        if(栈顶与pop的top一样)
        {
           执行pop;
        }
        else
        {
           错误;
        }
    }
    

    相当于对新栈要遍历一遍故时间复杂度为O(n),空间复杂度为O(n)

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

    优势:执行思路清晰,明确找到需要判断的点,构建新栈与pop进行一 一比较。
    难点:需要想到构建新栈导入push,利用栈的特性,一 一与pop进行逆序匹对。

  • 相关阅读:
    Python Scrapy框架
    Python Mongo数据库
    Python Selenium框架
    Python BeautifulSoup库使用
    Python 存入三大文件
    Python Xpath的解析,应用
    Python Requests 高级
    错误码:2003 不能连接到 MySQL 服务器在 (10061)
    MySQL连接本地数据库时报1045错误的解决方法
    iWebShop安装教程
  • 原文地址:https://www.cnblogs.com/960223447a/p/14614642.html
Copyright © 2011-2022 走看看