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;		//top为栈顶指针
    } Stack;
    typedef Stack *SqStack;
    

    初始化:

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

    入栈出栈:

    bool Push(SqStack &s,ElemType e)
    {
        if(s->top == MAXSIZE - 1)    //判断是否栈满
        {
            return false;
        }
        s->data[s->top++] = e;    //入栈
        return true;
    }
    
    bool Pop(SqStack &s,ElemType e)
    {
        if(StackEmpty(s))    //判断是否为空栈
        {
            return false;
        }
        e = s->data[s->top--];    //退栈
        return true;
    }
    

    销毁栈:

    void DestroyStack(SqStack s)
    {
       delete s;
    }
    

    链栈的结构、操作函数

    结构:

    操作函数:
    定义:

    typedef struct StackNode
    {
        ElemType data;
        struct StackNode *next;
    }Node,*Stack;
    

    初始化:

    bool InitStack(Stack &s)
    {
        s = NULL;
        return true;
    }
    

    入栈出栈:

    void Push(Stack& s, ElemType e)
    {
    	Stack p;
    	p = new Node;
    	p->data = e;		//新建节点p
    	p->next = s->next;	//插入*p节点作为开始节点
    	s->next = p;
    }
    
    bool Pop(Stack& s, ElemType& e)
    {
    	Stack p;
    	if (StackEmpty(s))		//栈空的情况
    		return false;
    	p = s->next;			//p指向开始节点,从栈顶开始出栈
    	e = p->data;
    	s->next = p->next;		//删除*p节点
    	delete p;				//释放*p节点
    	return true;
    }
    

    1.2 栈的应用

    括号匹配检验

    假设表达式中包含三种括号:圆括号、方括号和花括号,并且它们可以任意嵌套。例如{()[{}]}或[{()}([])]等为正确格式,而{[}()]或[({)]为不正确的格式。
    算法需要一个栈,在读入字符的过程中,如果是左括号,则直接入栈,等待相匹配的同类右括号;如果是右括号,且与当前栈顶左括号匹配,则将栈顶左括号出栈,如果不匹配则属于不合法的情况。另外,如果碰到一个右括号,而堆栈为空,说明没有左括号与之匹配,则非法。那么,当字符读完的时候,如果是表达式合法,栈应该是空的,如果栈非空,那么则说明存在左括号没有相应的右括号与之匹配,也是非法的情况。

    #include<iostream>
    #include<stack>
    #include<string>
    #include<vector>
    using namespace std;
    bool MatchBrackets(string braket_st);
    int main()
    {
    	string bracket_str;
    	cin >> bracket_str;
    	bool temp;
    	temp = MatchBrackets(bracket_str);
    	return 0;
    }
    bool MatchBrackets(string braket_st)
    {
    	stack<char> st;//初始化栈
    	int i;
    	for (i = 0; i < braket_st.size(); i++)
    	{
    		if (braket_st[i] == '(')
    			st.push(braket_st[i]);//入栈
    
    		else if (braket_st[i] == ')')
    		{
    			if (st.empty())//栈为空
    			{
    				cout << "no";
    				return false;
    			}
    
    			if (st.top() != '(')
    			{
    
    				cout << st.top() << endl;//取栈顶元素
    				cout << "no";
    
    			}
    			else//成功
    			{
    				st.pop();//输出
    
    			}
    		}
    
    		if (braket_st[i] == '[')
    			st.push(braket_st[i]);//输入
    		else if (braket_st[i] == ']')
    		{
    			if (st.empty())//栈为空
    			{
    				cout << "no";
    				return false;
    			}
    
    
    			if (st.top() != '[')
    			{
    
    				cout << st.top() << endl;//取栈顶元素
    				cout << "no";
    
    			}
    			else//成功
    			{
    				st.pop();
    
    			}
    		}
    
    		if (braket_st[i] == '{')
    			st.push(braket_st[i]);//输入
    		else if (braket_st[i] == '}')
    		{
    			if (st.empty())//栈空
    			{
    				cout << "no";
    				return false;
    			}
    
    
    			if (st.top() != '{')
    			{
    
    				cout << st.top() << endl;//取栈顶元素
    				cout << "no";
    
    			}
    			else
    			{
    				st.pop();
    			}
    		}
    
    	}
    
    	if (st.empty() && braket_st[i] == '')//找到配对并且扫描完成后栈为空
    	{
    		cout << "yes";
    		return true;
    	}
    	else if (!st.empty())//非空条件下.不配对
    	{
    		cout << st.top() << endl << "no";
    		return false;
    	}
    
    }
    
    

    1.3 队列


    注:包括顺序队列和环形队列

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

    定义:

    typedef struct 
    {     ElemType data[MaxSize]; 
          int front,rear;      //队首和队尾指针
    }Queue;
    typedef Queue *SqQueue;
    

    初始化:

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

    入队出队:

    bool enQueue(SqQueue &q,ElemType e)
    {  
        if (q->rear+1==MaxSize)	   return false;
                                           //队满上溢出
    	q->rear=q->rear+1;
    	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;
    	e=q->data[q->front];
    	return true;
    }
    

    销毁

    void DestroyQueue(SqQueue &q)
    {
      delete q;
    }
    

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

    定义:

    typedef struct 
    {	
      ElemType data[MaxSize];
      int front,rear;	
    } Queue;
    typedef Queue *SqQueue;
    

    初始化:

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

    出队入队:

    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;
    }
    

    注:循环队列长度=Q.rear-Q.front+MAXQSIZE)%MAXQSIZE

    链队列的结构、操作函数

    定义:

    typedef struct QNode{
       QElemType   data;
       struct Qnode  *next;
    }Qnode, *QueuePtr;//定义节点类型
    typedef struct {
       QueuePtr  front;            //队头指针   
       QueuePtr  rear;             //队尾指针
    }LinkQueue;  //定义队列类型
    

    初始化:

    Status InitQueue (LinkQueue &Q)
    {
       Q.front=Q.rear=new QNode; 
        if(!Q.front) exit(OVERFLOW);
        Q.front->next=NULL;
         return OK;
    }
    

    入队出队:

    Status EnQueue(LinkQueue& Q, QElemType e)
    {
    	p = (QueuePtr)malloc(sizeof(QNode));
    	if (!p) exit(OVERFLOW);
    	p->data = e; p->next = NULL;
    	Q.rear->next = p;
    	Q.rear = p;
    	return OK;
    }
    
    Status DeQueue(LinkQueue& Q, QElemType& e)
    {
    	if (Q.front == Q.rear) return ERROR;
    	p = Q.front->next;
    	e = p->data;
    	Q.front->next = p->next;
    	if (Q.rear == p) Q.rear = Q.front;
    	delete p;
    	return OK;
    }
    

    队列应用,要有具体代码操作。
    破解迷宫:
    使用队列来求解,假设当前点位为(x, y),在队列中的索引为front,遍历该位置的四个方位,如果方位可走则入队,并记录这个方位元素的前驱为front。如下图所示,当前点位上方的点位不可走,不入队;右方可走,入队;下方可走入队;左方可走入队;然后将front++,这时候当前点位变成(x, y+1),继续遍历它的四个方位,淘汰掉不可走的,可走的方位都会入队…。这样一层一层向外扩展可走的点,所有可走的点位各个方向都会尝试,而且机会相等,直到找到出口为止,这个方法称为“广度优先搜索方法”。然后我们从出口反向找其上一个方块的下标,直到下标为0,这个反向过程就能找到最短路径。

    public static QueueByArray<MazeElem> getMazePathByArrayQueue(int[][] maze, int startX,
                                                                     int startY, int endX, int endY){
            int x, y, di;
    
            QueueByArray<MazeElem> queue = new QueueByArray();
            //入口元素进队
            MazeElem elem = new MazeElem(startX, startY, 0,-1);
            queue.enQueue(elem);
            maze[startX][startY] = -1;  //将入口元素置为-1,避免回过来重复搜索
    
            int front = 0;  //记录当前操作的可走方块在队列中的索引
            //队列不为空且未找到路径时循环
            while(front<=queue.getRear()){
                x = queue.getElement(front).x;
                y = queue.getElement(front).y;
                if(x == endX && y == endY){  //找到了出口
                    int k = front, j;
                    //反向找到最短路径,将该路径上的方块的pre设置为-1
                    do{
                        j = k;
                        k = queue.getElement(k).pre;   //上一个可走方块索引
                        queue.getElement(j).pre = -1;  //将路径上的元素的pre值为-1
                    }while(k!=0);
                    //返回队列,队列中pre为-1的元素,构成最短路径
                    return queue;
                }
                for(di = 0; di<4; di++){   //循环扫描每个方位,把每个可走的方块插入队列中
                    switch (di){
                        case 0:     //上
                            x = queue.getElement(front).x-1;
                            y = queue.getElement(front).y;
                            break;
                        case 1:     //右
                            x = queue.getElement(front).x;
                            y = queue.getElement(front).y+1;
                            break;
                        case 2:     //下
                            x = queue.getElement(front).x+1;
                            y = queue.getElement(front).y;
                            break;
                        case 3:     //左
                            x = queue.getElement(front).x;
                            y = queue.getElement(front).y-1;
                            break;
                    }
                    if(x>=0 && y>=0 && x<maze.length && y<maze[0].length){
                        if(maze[x][y] == 0){
                            //将该相邻方块插入队列
                            queue.enQueue(new MazeElem(x, y, 0, front));
                            maze[x][y] = -1;   //赋值为-1,避免回过来重复搜索
                        }
                    }
                }
                front ++;
            }
            return null;
        }
    

    2.PTA实验作业(4分)

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

    2.1 符号配对

    7-2 jmu-ds-符号配对

    2.1.1 解题思路及伪代码

    遍历输入数据,取符号置于全新的数组中,然后依次入栈并加以判断

    2.1.2 总结解题所用的知识点

    1.数组的应用
    2.栈的应用

    2.2 银行业务队列简单模拟

    7-6 银行业务队列简单模拟 (25 分)

    2.2.1 解题思路及伪代码

    用A,B两个队列分别存储顾客编号。A存储顾客编号为奇数的,则B存储顾客号为偶数。当A窗口没有解决完2个顾客的时且A队列不空,则A出队;当A解决完2人且B队列不空,则B出队

    2.2.2 总结解题所用的知识点

    1.采用queue库函数更加便捷,获取队首元素
    2.需要借用flag来判断空格的输入输出
    3.当A或B两个有一个队列为空就退出循环,然后单独输出不为空的队列

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

    从键盘上输入一个逆波兰表达式,用伪码写出其求值程序。规定:逆波兰表达式的长度不超过一行,以$符作为输入结束,操作数之间用空格分隔,操作符只可能有+、-、、/四种运算。例如:234 34+2$
    答:[题目分析]逆波兰表达式(即后缀表达式)求值规则如下:设立运算数栈OPND,对表达式从左到右扫描(读入),当表达式中扫描到数时,压入OPND栈。当扫描到运算符时,从OPND退出两个数,进行相应运算,结果再压入OPND栈。这个过程一直进行到读出表达式结束符$,这时OPND栈中只有一个数,就是结果。

         float expr( )
         //从键盘输入逆波兰表达式,以‘$’表示输入结束,本算法求逆波兰式表达式的值。
         {float OPND[30]; // OPND是操作数栈。
          init(OPND); //两栈初始化。
         float num=0.0; //数字初始化。
         scanf (“%c”,&x);//x是字符型变量。
         while(x!=’$’)
         {switch
              {case‘0’<=x<=’9’:while((x>=’0’&&x<=’9’)||x==’.’) //拼数
                   if(x!=’.’) //处理整数
         {num=num*10+(ord(x)-ord(‘0’)); scanf(“%c”,&x);}
                   else //处理小数部分。
                   {scale=10.0; scanf(“%c”,&x);
                   while(x>=’0’&&x<=’9’)
                   {num=num+(ord(x)-ord(‘0’)/scale;
                   scale=scale*10; scanf(“%c”,&x); }
                   }//else
                   push(OPND,num); num=0.0;//数压入栈,下个数初始化
         case x=‘ ’:break; //遇空格,继续读下一个字符。
         case x=‘+’:push(OPND,pop(OPND)+pop(OPND));break;
         case x=‘-’:x1=pop(OPND);x2=pop(OPND);push(OPND,x2-x1);break;
         case x=‘*’:push(OPND,pop(OPND)*pop(OPND));break;
         case x=‘/’:x1=pop(OPND);x2=pop(OPND);push(OPND,x2/x1);break;
         default: //其它符号不作处理。
         }//结束switch
         scanf(“%c”,&x);//读入表达式中下一个字符。
         }//结束while(x!=‘$’)
         printf(“后缀表达式的值为%f”,pop(OPND));
         }//算法结束。
    
  • 相关阅读:
    laravel 查询指定字段的值
    laravel 连表查询数据库
    jar包在控制台下运行
    jsp 中文乱码
    PHP垃圾回收深入理解
    php在foreach中使用引用赋值&可能遇到的问题
    接口和抽象类有什么区别
    关于php优化 你必须知道的一些事情
    yii 表单小部件
    yii 表单小部件的使用方式
  • 原文地址:https://www.cnblogs.com/denghong88/p/14619838.html
Copyright © 2011-2022 走看看