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

    0.PTA得分截图

    1.本周学习总结

    1.1 总结栈和队列内容

    思维导图

    • ·栈的存储结构及操作
      栈:一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算,对于栈的操作有进栈,出栈,销毁栈,初始化栈与取栈顶元素。栈最需要注意的是栈是后进先出表。
    顺序栈
    
    typedef struct
    {
    	ElemType str[MaxSize];
    	int top;
    }SqStack;
    void InitStack(SqStack*& st)            //初始换栈
    {
    	st = new SqStack;
    	st->top = -1;
    }
    bool Push(SqStack*& st, ElemType string)            //入栈
    {
    	int i;
    	if (st->top == MaxSize - 1)
    	{
    		return false;
    	}
    	else
    	{
    		st->top++;
    		st->str[st->top] = string;
    		return true;
    	}
    }
    bool Pop(SqStack*& st, ElemType& e)                //出栈
    {
    	if (st->top == -1)
    	{
    		return false;
    	}
    	else
    	{
    		e = st->str[st->top];
    		st->top--;
    		return true;
    	}
    }
    
    
    链栈
    
    typedef struct SNode {
    	int data;
    	SNode *next;
    }SNode;
    typedef struct
    {
    	SNode *top;
    }LStack;
    void initLStack(LStack &S)             //初始化链栈
    {
    	S.top = new SNode;
    	S.top->data = NULL;
    	S.top->next = NULL;
    	return;
    }
    bool Empty(LStack S)             //判断栈是否为空
    {
    	if (S.top->next)
    		return false;
    	else
    		return true;
    }
    void push(LStack &S,int e)             //入栈
    {
    	SNode* newNode = new SNode;
    	newNode->data = e;
    	newNode->next = S.top->next;
    	S.top->next = newNode;
    	S.top->data++;
    	return;
    }
    
    bool popLStack(LStack &S)                 //出栈
    {
    	int e;
    	if (isEmptyLStack(S)) 
            {
                    return false;
    	}
    	SNode* delNode = S.top->next;
    	S.top->next = delNode->next;
    	e = delNode->data;
    	delete delNode;
    	S.top->data--;
    	return true;
    }
    
    • ·栈的应用
    检测括号是否匹配
    
    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<stack>
    using namespace std;
    #define Max 80
    typedef int ElementType;
    bool judge(string str);
    
    int main()
    {
    	string str;
    	cin >> str;
    	if (judge(str))
    		cout << "yes";
    	else
    		cout << "no";
    	return 0;
    }
    
    bool judge(string str)
    {
    	char e;
    	stack<char>st;
    	int flag = 1, i = 0;
    	while (str[i])
    	{
    		if (str[i] == '(' || str[i] == '[' || str[i] == '{')
    			st.push(str[i]);
    		else if (str[i] == ')' || str[i] == ']' || str[i] == '}')
    		{
    			if (st.empty())
    				return false;//如果栈已空,没有俞左括号配对,则错误
    			e = st.top();//取栈顶
    			st.pop();//去栈顶
    			switch (str[i])
    			{
    			case')':if (e != '(')flag = 0; break;
    			case']':if (e != '[')flag = 0; break;
    			case'}':if (e != '{')flag = 0; break;
    			}
    		}
    		i++;
    	}
    	if (st.empty() && flag == 1)
    		return true;//如果栈已经空了那就是对的
    	else
    	{
    		e = st.top();
    		cout << e << endl;
    		return false;
    	}
    }
    
    
    递归
    
    int fun(int n)//计算斐波那契数列第n项的值
    {
           if(n==1||n==2)
        {
                  return 1;
        }
        else
        {
                  return fun(n-1)+fun(n-2);
        }
    }
    
    
    
    int fun(int n)//n的阶乘
    {
           if(n==1)
        {
                  return 1;
        }
        else
        {
                  return fun(n-1)*n;
        }
    }
    
    进制转换
    
    bool Conversion(stack& s,int data,int N)
    {
         if(N<=0)
         {
            return false;
         }
         while (data)
         {
             push(s,data%N);
             data = data/N;
         }
    
         while (s)
         {
             pop(s);
         }
        return true;
     }
    
    • ·队列的存储结构及操作
    顺序队
    
    #define MaxSize 10  //队列的最大容量
    typedef int DataType;  //队列中元素类型
    typedef struct Queue
    {
        DataType Queue[MaxSize];
        int fornt;   //队头指针
        int rear;    //队尾指针
    }SeqQueue;
    
        
    void InitQueue(SeqQueue *SQ)        //队列初始化,将队列初始化为空队列
    {
        SQ->fornt = SQ->rear = 0;  //把对头和队尾指针同时置0
     }
    
        
    
    int IsEmpty(SeqQueue* SQ)            //判断队列为空
    {
        if (SQ->fornt == SQ->rear)
        {
            return 1;
        }
        return 0;
    }
    
    
    
    int IsFull(SeqQueue* SQ)        //判断队列是否为满
    {
        if (SQ->rear == MaxSize) 
        {
            return 1;
        }
        return 0;
    }
    
    
    void EnterQueue(SeqQueue* SQ,DataType data)        //入队,将元素data插入到队列SQ中
    
    {
        if (IsFull(SQ))
        {
            printf("队列已满
    ");
            return 0;
        }
        SQ->Queue[SQ->rear] = data;  //在队尾插入元素data
        SQ->rear = SQ->rear + 1;     //队尾指针后移一位
    }
    
    
    int DeleteQueue(SeqQueue* SQ,DataType* data)        //出队,将队列中队头的元素data出队,出队后队头指针front后移一位
    {
        if (IsEmpty(SQ))
        {
            printf("队列为空!
    ");
            return 0;
        }
        *data = SQ->Queue[SQ->fornt];   //出队元素值
        SQ->fornt = (SQ->fornt)+1;      //队尾指针后移一位
        return 1;
    }
    
    
    
    int GetHead(SeqQueue* SQ,DataType* data)        //获取队首元素
    {
        if (IsEmpty(SQ))
        {
            printf("队列为空!
    ");
        }
        return *data = SQ->Queue[SQ->fornt];  
    }
    
    
    
    void DestoryQueue(SeqQueue* SQ)            //销毁链表
    {
        SQ->fornt = SQ->rear = 0;
    }
    
    
    void PrintQueue(SeqQueue* SQ)        //打印队列中的与元素
    
    {
        assert(SQ);    
        int i = SQ->fornt;
        while(i<SQ->rear)
        {
            printf("%-3d", SQ->Queue[i]);
            i++;
        }
        printf("
    ");
    }
    
    链队
    
    typedef struct QueueNode
    {
        int e;//数据域
        struct QueueNode* next;//指针域
    }QueueNode,*LinkQueuePoi;
    typedef struct LinkQueue
    {
        LinkQueuePoi front;//指向头结点
        LinkQueuePoi rear;//指向队尾
    }LinkQueue;
    
    
    Status InitLinkQueue(LinkQueue* queue)        //初始化链队列.链队列为空时,链队列队头指针队尾指针均指向头结点
    {
        //空指针
        if (!queue)
        {
            return false;
        }
        QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));//头结点
        node->next = NULL;
        queue->front = queue->rear = node;
        return true;
    }
    Status CleaerLinkQueue(LinkQueue* queue)
    {
        //空指针
        if (!queue)
        {
            return false;
        }
        //空链队列
        if (queue->front == queue->rear)
        {
            return false;
        }
        QueueNode* node = queue->front->next;//队头元素
        while (node)
        {  
            queue->front->next = node->next;//指向新的队头结点
            if (queue->rear == node)//当删除的是队尾元素时,将队尾指针指向头结点
            {
                queue->rear = queue->front;
            }
            free(node);//释放旧的队头结点
            node = queue->front->next;
        }
        return true;
    }
    
    Status EmptyLinkQueue(LinkQueue* queue)        //判断链队列是否为空队列
    {
        //空指针
        if (!queue)
        {
            return ERROR;
        }
        //空链队列
        if (queue->front == queue->rear)
        {
            return    ;
        }
            return false;
    }
        /*
        获取链队列长度
        */
    int LengthLinkQueue(LinkQueue* queue)
        {
        //空指针
        if (!queue)
        {
            return false;
        }
        //空链队列
        if (queue->front == queue->rear)
        {
            return 0;
        }
        QueueNode* node = queue->front->next;
        int num = 0;
        while (node)
        {
            node = node->next;
            num++;
        }
        return num;
    }
    
    bool AddQueue(LinkQueue* queue,EleType e)            //在链队列队尾添加元素,先将新元素添加到链表尾部,然后将队列尾指针指向这个新元素
    {
        //空指针
        if (!queue)
        {
            return flase;
        }
        QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
        if (!node)
        {
            return false;
        }
        node->next = NULL;
        node->e = e;
        queue->rear->next = node;//将新结点添加到链表表中
        queue->rear = node;//队尾指针指向新的队尾结点
        return true;
    }
    Status DelQueue(LinkQueue* queue, EleType *e)            //从链队列中删除队头元素,先将头结结点指向新的队头结点,然后释放原来的队头结点
    {
        //空指针
        if (!queue)
        {
            return false;
        }
        //注意queue->front是头结点,头结点指向的结点才是队头结点
        QueueNode* node = queue->front->next;//旧队头结点
        *e = node->e;
        queue->front->next = node->next;//队头指针指向新的队头结点
        //当删除的是队尾元素时,将队尾指针指向头结点
        if (node = queue->rear)
        {
               queue->rear = queue->front;
        }
        return  true;
    }
    void PrintfLinkQueue(LinkQueue* queue)            //输出链表
    {
         if (!queue)
         {
             return;
         }
         QueueNode* node = queue->front->next;
         while (node)
         {
             printf("%d,", node->e);
             node = node->next;
         }
         printf("
    ");
         return;
    }
    
    • ·队列应用
    广度优先搜索解决迷宫问题
    
    #include<iostream>
    #define MAX 1000
    using namespace std;
    
    int m, n;
    int mg[MAX][MAX];
    int xi, yi, xe, ye;
    typedef struct
    {
    	int i, j;
    	int pre;
    }BOX;
    
    typedef struct
    {
    	BOX data[MAX];
    	int front, rear;
    }QuType;
    
    void InitQueue(QuType*& qu);
    bool QueueEmpty(QuType* qu);
    void enQueue(QuType*& qu, BOX& e);
    void deQueue(QuType*& qu, BOX& e);
    void InitMg(int mg[][MAX]);
    void DestroyQueue(QuType*& qu);
    void count(QuType* qu, int front);
    bool mgpathl(QuType*& qu, int xi, int yi, int xe, int ye);
    
    int main()
    {
    
    	QuType* qu;
    	InitQueue(qu);
    	InitMg(mg);
    	cin >> xi >> yi;
    	cin >> xe >> ye;
    	mgpathl(qu, xi, yi, xe, ye);
    	return 0;
    }
    void InitMg(int mg[][MAX])
    {
    	int num;
    	cin >> m >> n;
    
    	for (int i = 0; i <= 1 + m; i++)
    	{
    		for (int j = 0; j <= 1 + n; j++)
    		{
    			if (i == 0 || j == 0 || i == m + 1 || j == 1 + n)
    			{
    				mg[i][j] = 1;
    			}
    		}
    	}
    	for (int i = 1; i <= m; i++)
    	{
    		for (int j = 1; j <= n; j++)
    		{
    			cin >> num;
    			mg[i][j] = num;
    		}
    	}
    }
    
    void InitQueue(QuType*& qu)
    {
    	qu = new QuType;
    	qu->front = -1;
    	qu->rear = -1;
    }
    void enQueue(QuType*& qu, BOX& e)
    {
    	qu->rear++;
    	qu->data[qu->rear] = e;
    }
    
    void deQueue(QuType*& qu, BOX& e)
    {
    	qu->front++;
    	e = qu->data[qu->front];
    }
    
    bool QueueEmpty(QuType* qu)
    {
    	if (qu->rear == -1)return true;
    	else return false;
    }
    void DestroyQueue(QuType*& qu)
    {
    	free(qu);
    }
    void count(QuType* qu, int front)                        //寻找出迷宫最短路径
    {
    	int k = front, j, ns = 0;
    	do
    	{
    		j = k;
    		k = qu->data[k].pre;
    		qu->data[j].pre = -1;
    	} while (k != 0);
    	k = 0;
    	while (k < MAX)
    	{
    		if (qu->data[k].pre == -1)
    		{
                            printf("(%d,%d)->", qu->data[k].i, qu->data[k].j);
    			ns++;
    		}
    		k++;
    	}
    	cout << ns;
    }
    
    bool mgpathl(QuType*& qu, int xi, int yi, int xe, int ye)            //寻找出迷宫路径
    {
    	BOX e;
    	int il,jl;
    	int i, j, find = 0, di;
    	e.i = xi;
    	e.j = yi;
    	e.pre = -1;
    	enQueue(qu, e);
    	mg[xi][yi] = -1;
    	while (qu->front != qu->rear && !find)
    	{
    		deQueue(qu, e);
    		i = e.i;
    		j = e.j;
    		if (i == xe && j == ye)
    		{
    			find = 1;
    			count(qu, qu->front);
    			return true;
    		}
    		for (di = 0; di < 4; di++)
    		{
    			for (di = 0; di < 4; di++)
    			{
    				switch (di)
    				{
    				case 0:il = i - 1; jl = j; break;
    				case 1:il = i; jl = j + 1; break;
    				case 2:il = i + 1; jl = j; break;
    				case 3:il = i, jl = j - 1; break;
    				}
    				if (mg[il][jl] == 0)
    				{
    					e.i = il;
    					e.j = jl;
    					e.pre = qu->front;
    					enQueue(qu, e);
    					mg[il][jl] = -1;
    				}
    			}
    		}
    	}
    	return false;
    }
    

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

    栈和队列相较于前一部分学的线性表,学习难度有所增大,可现的功能更多。在使用线性栈和线性队列时,需要考虑栈和队列是否为满。
    而使用链栈和链队时,我们则不需要考虑栈或队列满的情况。
    循环队列的空满判断条件需要对最大空间进行取余。

    2.PTA实验作业

    2.1.题目1:7-8 电路布线

    2.1.1代码截图(注意,截图,截图,截图。不要粘贴博客上。)




    2.1.2本题PTA提交列表说明。


    Q1:代码虽然找到了出迷宫路径,但是该路径并非最短路径
    A1:发现是在寻找最短路径时,判断出了错误
    Q2:复制代码到PTA时少复制了一个头文件
    A2:重新复制了一遍

    2.2.题目2:银行排队问题之单队列多窗口服务

    2.1.1代码截图(注意,截图,截图,截图。不要粘贴博客上。)



    2.1.2本题PTA提交列表说明。


    Q1:三次错误原因相同,在统计等待时间时出了问题,在等待时,一开始统计了所有窗口的等待时间
    A2:改后,一个人只统计最短窗口的等待时间

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

    3.1 列车调度

    两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?

    3.1.1 该题的设计思路


    T=O(n)
    S=O(1)

    3.1.2 该题的伪代码

    定义字符数组str1,str2
    输入1,2号铁轨列车顺序
    建栈S
    定义指针数组way
    while(str1[i]!='')
        如果 str1[i]与str2[j]相等
            路径为1->2
        如果栈顶与str2[j]相等
            路径为3->2,栈顶元素出栈
        如果str1[i]与str2[j]不相等
            路径为1->3,str[i]入栈
    如果S不为空
        while栈S不为空
           遍历str2余下元素
                如果flag==0而且栈顶元素与str2[t]相等
                    路径为3->2,出栈
                否则flag=1,出栈
    如果flag为0,输出指针数组way
    否则输出Are you kidding me?
    

    3.1.3 运行结果


    没看出来错在哪,第一个数据不对。

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

    加强了对栈空栈满的判断。

    3.2 用一个栈实现另一个栈的排序

    一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。除此之外,可以申请新的变量,但不能申请额外的数据结构。如何完成排序?

    3.2.1 该题的设计思路

    题中给出了两个栈,我们可以将要排序的栈记为stack,辅助栈记为help。要实现stack中的元素从顶到底按从大到小排序,则入栈的元素顺序应该为:从小到大。所以,help栈中元素从顶到底要实现由小到大的顺序。那么这就是解题关键了,我们只要实现这个就好。
    T=O(n)
    S=O(n)

    3.2.2 该题的伪代码

    在stack上执行pop操作,弹出的元素记为cur。
    若cur小于或者等于help的栈顶元素,则将cur直接压入help。
    (!!!保持help从栈顶到栈底由小到大的顺序)
    2.若cur大于help的栈顶元素(注意:若此时将cur压入help,则会违反help栈
    顶到底由小到大的顺序),则将help的元素逐一弹出,逐一压入stack,直到cur小于
    或者等于help的栈顶元素,再将cur压入help。
    3.重复以上操作,直到stack中的全部元素都压入到help。最后将help中的所有
    元素逐一压入stack,即完成排序。

    3.2.3 运行结果

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

    考验做题者对栈的灵活运用

  • 相关阅读:
    使用jquery-qrcode生成二维码
    ASP.NET匿名对象与集合的使用
    ASP.NET Core 之跨平台的实时性能监控
    centos7如何将docker容器配置成开机自启动
    linux 查看系统信息命令
    基于.NET CORE微服务框架 -浅析如何使用surging
    Docker 两键创建 ZeroTier moon 节点
    kubernetes-dashboard获取令牌登陆
    docker环境下使用gitlab,gitlab-runner 为 NetCore 持续集成
    Docker For MYSQL 8.0 特别注意修复数据库新的验证方式
  • 原文地址:https://www.cnblogs.com/whb1/p/12546143.html
Copyright © 2011-2022 走看看