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

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

    0.PTA得分截图

    栈和队列题目集总得分,请截图,截图中必须有自己名字。题目至少完成2/3(不包括选择题),否则本次作业最高分5分。

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

    1.1 栈

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

    • 顺序栈的结构、操作函数

      操作函数

      • 结构体

        struct SNode {
            ElementType* Data;  /* 存储元素的数组   */
            Position Top;     /* 栈顶指针 */
            int MaxSize;
        };
        
      • 入栈

      void PushStack(Stack S, ElementType x)
      {
          if (S->Top == S->MaxSize)
          {
              printf("Stack Full
      ");
              return;
          }
          S->Top++;
          S->Data[S->Top] = x;
      }
      
      • 出栈
      ElementType PopStack(Stack S)
      {
          if (S->Top == -1)
          {
              printf("Stack Empty
      ");
              return 0;
          }
          return S->Data[S->Top--];
      }
      
      • 栈空
      int StackEmpty(Stack S)
      {
          if (S->Top == -1)
              return 1;
          else
              return 0;
      }
      
    • 链栈的结构、操作函数

      操作函数

      • 结构体定义:
      typedef int Elmetype;
      struct SNode
      {
      	Elmetype data;
      	struct SNode* next;
      };
      typedef struct SNode* LinkStack;
      
      • 进栈:
      void Push(LinkStack& S, Elmetype X)
      {
      	LinkStack NewS = new SNode;
      	/*数据载入*/
      	NewS->data = X;
      	/*头插法插入新数据*/
      	NewS->next = S->next;
      	S->next = NewS;
      }
      
      • 出栈:
      bool Pop(LinkStack& S, Elmetype& e)
      {
      	/*首先要判断栈顶是否为空*/
      	if (S->next == NULL)
      	{
      		return false;
      	}
      	e = S->next->data;
      	LinkStack delSNode = S->next;
      	S->next = delSNode->next;
      	delete delSNode;
      	return true;
      }
      
      • 取栈顶元素:
      void DestoryLinkStack(LinkStack& S)
      {
      	LinkStack delS = S;
      	while (S != NULL)
      	{
      		S = S->next;
      		delete delS;
      		delS = S;
      	}
      }
      

    1.2 栈的应用

    • 表达式求值
    • 表达式转换
    • 符号的配对(创建一个栈,在读入字符的过程中,如果是左括号,则直接入栈,等待相匹配的同类右括号;如果是右括号,且与当前栈顶左括号匹配,则将栈顶左括号出栈)
    • 迷宫问题

    1.3 队列

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

    队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头.

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

      • 结构体定义
      typedef struct
      {
          ElemType data[MaxSize];
          int front, rear;
      }SqQueue;
      typedef SqQueue* Queue;
      
      • 初始化队列
      void InitQueue(Queue Q)
      {
          Q = (Queue)malloc(sizeof(SqQueue)*Max);
          Q->front = Q->rear = 0;
      }
      
      • 销毁队列
      void DestroyQueue(Queue Q)
      {
          free(Q);
      }
      
      • 判断队列是否为空
      bool QueueEmpty(Queue Q)
      {
          return (Q->front == Q->rear);
      }
      
      • 入队
      bool EnQueue(Queue Q,ElemType e)
      {
          if(Q->rear == MaxSize)
              return false;
          Q->data[Q->rear++] = e;
          return true;
      }
      
      • 出队
      bool DeQueue(Queue Q,ElemType &e)
      {
          if(Q->front == Q->rear)
              return false;
          e = Q->data[Q->front++];
          return true;
      }
      
    • 环形队列的结构、操作函数

      • 结构体定义
      typedef struct
      {
          ElemType data[MaxSize];
          int front, rear;
      }SqQueue;
      typedef SqQueue* Queue;
      
      • 初始化队列
      void InitQueue(Queue Q)
      {
          Q = (Queue)malloc(sizeof(SqQueue)*Max);
          Q->front = Q->rear = 0;
      }
      
      • 销毁队列
      void DestroyQueue(Queue Q)
      {
          free(Q);
      }
      
      • 判断队列是否为空
      bool QueueEmpty(Queue Q)
      {
          return (Q->front == Q->rear);
      }
      
      • 入队
      bool EnQueue(Queue Q,ElemType e)
      {
          if((Q->rear +1) % MaxSize == Q->front)
              return false;
          Q->data[Q->rear] = e;
          Q->rear = (Q->rear + 1) % MaxSize;
          return true;
      }
      
      • 出队
      bool DeQueue(Queue Q,ElemType &e)
      {
          if(Q->front == Q->rear)
              return false;
          e = Q->data[Q->front];
          Q->front = (Q->front + 1) % MaxSize;
          return true;
      }
      
    • 链队列的结构、操作函数

      • 结构体定义
      typedef struct QNode    /* 声明链式队列的结点 */
      {
          int data;
          struct QNode *next;
      }Node;
      typedef struct QueuePoint    /* 声明链式队列的首尾指针 */
      {
          Node *front;
          Node *rear;
      };
      typedef QueuePoint* Queue;
      
      • 初始化队列
      Queue InitQueue (Queue Q)    
      {                        
          Q = (Queue)malloc(sizeof(QueuePoint));
          Q->front = Q->rear = NULL;
      
          return Q;
      }
      
      • 销毁队列
      void DestroyQueue(Queue Q)
      {
          Node* pre = Q->front,* p;
          if(pre != NULL)
          {
              p = pre->next;
              while(p != NULL)
              {
                  free(pre);
                  pre = p;p = p->next;
              }
              free(pre);
          }
          free(Q);
      }
      
      • 判断队列是否为空
      bool QueueEmpty(Queue Q)
      {
          return (Q->rear == NULL);
      }
      
      • 入队
      void EnQueue(Queue Q,ElemType e)
      {
          Node* p;
          p = (Node*)malloc(sizeof(Node));
          p->data = e;
          p->next = NULL;
          if(Q->rear == NULL)
              Q->front = Q->rear = p;
          else
          {
              Q->rear->next = p;
              Q->rear = p;
          }
      }
      
      • 出队
      bool DeQueue(Queue Q,ElemType &e)
      {
          Node* p;
          if(Q->rear == NULL)
              return false;
          p = Q->front;
          if(Q->front == Q->rear)
              Q->front = Q->rear = NULL;
          else
              Q->front = Q->front->next;
          e = p->data;
          free(p);
          return true;
      }
      
    • 队列应用,要有具体代码操作。

      舞伴问题

      int QueueLen(SqQueue Q){//队列长度
      return (Q->rear -Q->front + MAXQSIZE ) % MAXQSIZE;
      
      }
      int EnQueue(SqQueue &Q, Person e){//入队
       Q->rear = (Q->rear + 1) %MAXQSIZE;
        	Q->data[Q->rear] = e;
        	return 0;
      }
      int QueueEmpty(SqQueue &Q){//判空
          if(Q->front==Q->rear){
              return 1;
          }else{
              return 0;
          }
      }
      int DeQueue(SqQueue &Q, Person &e){//出队
      //就很神奇,把出队那个存到e中
          Q->front=(Q->front+1)%MAXQSIZE;    
          e=Q->data[Q->front];
          return 0;
      }
      void DancePartner(Person dancer[], int num){
         /*
         *函数作用:
         *1.将Person里存的人分到Mdancers, Fdancers两个队列
         *2.Mdancers, Fdancers一比一配队出列
         */
         //Mdancers, Fdancers
         for(int i=0;i<num;i++){
          if(dancer[i].sex=='M'){
              EnQueue(Mdancers,dancer[i]);
          }else{
              EnQueue(Fdancers,dancer[i]);
          }
         }
         while(QueueEmpty(Mdancers)!=1&&QueueEmpty(Fdancers)!=1){
          Person x,y;
          DeQueue(Mdancers, x);
          DeQueue(Fdancers, y);
          cout<<y.name<<"  "<<x.name<<endl;
         }
      }
      
      

    2.PTA实验作业(4分)

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

    2.1 符号配对

    #include<iostream>
    #include<string>
    #include<stack>
    using namespace std;
    int main() {
    	string s;
    	char b[7];
    	b[1] = '('; b[2] = ')'; b[3] = '['; b[4] = ']'; b[5] = '{'; b[6] = '}';//用来存储括号,省掉三分之二的代码量。如果你代码超过100行了,那很有可能是因为用了6个if而不是2个。
    	int find = 0;
    	bool isasimple = false;
    	stack<char> bracket;//特地百度了一下括号的英文单词,就用他做栈名字吧。
    	while (1) {
    		getline(cin, s);
    		if (s==".") goto zoulou;//当结束时,直接“zoulou”(走咯)
    		for (int i = 0; i < s.length(); i++) {//*/是两个字符比较特殊,单独讨论
    			if (s[i] == '/' && 1 + i < s.length())
    				if (s[i + 1] == '*') {
    					bracket.push(s[i]);//我们将两个字符以/的形式保存,这样方便
    					i++;//因为这时候是两个字符
    					continue;
    				}
    			if (s[i] == '*' && 1 + i < s.length())
    				if (s[i + 1] == '/')
    				{
    					if (bracket.empty()) {
    						cout << "NO" << endl << "?-*/" << endl;
    						return 0;
    					}
    					else {
    						if (bracket.top() != '/') {
    							cout << "NO" << endl << bracket.top() << "-?" << endl;
    							return 0;
    						}
    						else {
    							bracket.pop();
    							i++;//弹栈是弹一个,但是让栈弹的却是两个字符
    							continue;
    						}
    					}
    				}
    			isasimple = false;
    			for (find = 1; find <= 6; find++) {
    				if (b[find] == s[i]) {//找一下是不是剩余的六个字符
    					isasimple = true; break;
    				}
    			}
    			if (isasimple) {
    				if (find % 2 == 1) {
    					bracket.push(s[i]);
    					continue;
    				}
    				else {
    					if (bracket.empty()) {
    						cout << "NO" << endl << "?-" << b[find] << endl;
    						return 0;
    					}
    					else {
    						if (bracket.top() == '/') {
    							cout << "NO" << endl <<"/*-?" << endl;
    							return 0;
    						}
    						else if (bracket.top() != b[find - 1]) {
    							cout << "NO" << endl << bracket.top() << "-?" << endl;
    							return 0;
    						}
    						else {
    							bracket.pop();
    							continue;
    						}
    					}
    				}
    			}
    		}
    	}
    zoulou:
    	if (bracket.empty()) {//走咯之后还没完,如果栈不是空的,也还会出错。
    		cout << "YES" << endl;
    	}
    	else {
    		cout << "NO" << endl << bracket.top() << "-?" << endl;
    	}
    	return 0;
    }
    
    

    2.1.1 解题思路及伪代码

    • 当左边一堆左括号时,右边出现一个右括号,此右括号与离他最近的一个左括号匹配。 就是我们一直以右括号为标准,当右括号出现时,我们就要找他左边的括号。 所以我们要保存左括号,由于这个性质,我们可以用栈保存左括号。
    • 思路:我们一直把左括号压入栈中,当找到有个右括号时,我们把它和栈顶元素比较。
      但是比较的时候,要看栈是否为空。非空的话我们可以比较。如果为空,那我们就保存这个右符号,同时设置一个flag变量。
      最终还要看一看栈里面是不是空的,如果是空的,且flag也没问题,那我们输出yes
      如果栈为空,但是flag标记了,那我们输出那个右符号
      如果栈不是空的,输出栈顶即可。

    2.1.2 总结解题所用的知识点

    • 顺序栈的结构

    • 顺序栈的出栈入栈操作

    • 递归函数的调用

    • 标准输入输出流的运用

    • 使用了hash表的知识,用hash表来存储会用到的符号。

    • 使用了STL库的string类。

    • 学会了利用string类的特点对多行元素进行有指定结束标志的读取。

    2.2 银行业务队列简单模拟

    #include <stdio.h>
    int main() 
    { 
    	int a[1010], b[1010];   //数组a,b用来存放A,B窗口的顾客 
    	int ca = 0,cb = 0;     //ca,cb分别代表窗口A、窗口B的人数 
    	
    	int n; 	//n为顾客总数 	
    	scanf("%d", &n); 
    	for (int i = 1; i <= n; i++) 
    	{ 
    		int temp; //顾客编号 
    		scanf("%d", &temp);
    		
    		//编号为偶数的去A窗口 ,否则去B窗口 
    		if (temp % 2)  
    			a[++ca] = temp; 
    		else 
    		b[++cb] = temp; 
    	} 
    	
    	int f = 0;//控制空格的输出 
    	int x = 1, y = 1; //x,y为a[],b[]下标,从1开始遍历(模拟队列,先进先出)
    	 
    	//A优先输出,A出两个,B出一个 
    	while (x <= ca || y <= cb) 
    	{ 
    		if (x <= ca) 
    		{ 
    			if (f++) 
    				printf(" "); 
    			printf("%d", a[x++]); 
    		} 
    		if (x <= ca) 
    		{ 
    			if (f++) 
    				printf(" "); 
    			printf("%d", a[x++]); 
    		} 
    		if (y <= cb) 
    		{ 
    			if (f++) 
    				printf(" "); 
    			printf("%d", b[y++]); 
    		} 
    	} 
    	return 0; 
    	}
    

    2.2.1 解题思路及伪代码

    emm,很尴尬没有用队列和栈QwQ

    2.2.2 总结解题所用的知识点

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

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

    注意:不能选教师布置在PTA的题目。完成内容如下。

    3.1 题目及解题代码

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

    #include<iostream>
    #include <stack>
    char s[4] = { 'q','a','b','c' };
    std::stack<int> a[4];
    bool move(int before, int after) {
    	if (a[before].empty())
    		return false;
    	if (!a[after].empty())
    		if ((a[after].top() - a[before].top()) < 0)
    			return false;
    	a[after].push(a[before].top());
    	a[before].pop();
    	printf("%c -> %c
    ", s[before], s[after]);//faster than cout
    	return true;
    }
    int main() {
    	int  N, count = 0;
    	std::cin >> N;
    	for (int i = 0; i < N; i++)
    		a[1].push(N - i);
    	if (N % 2 == 1) {
    		s[2] = 'c'; s[3] = 'b';
    	}
    	while (++count) {
    		move((count - 1) % 3 + 1, (count) % 3 + 1);
    		if (!move((count - 1) % 3 + 1, (count + 1) % 3 + 1)&&!move((count + 1) % 3 + 1, (count - 1) % 3 + 1))
    				break;
    	}
    }
    

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

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

    所有的汉诺塔移动可以总结为重复的两步,我们假设现在最小的圆盘在a柱子上,柱子为a,b,c

    第一步:将最小圆盘移动到下一个柱子上,也就是b

    第二步:对a柱子和c柱子进行顶上最小的元素进行判断,把小一点的那个圆盘移动到大一点的那个圆盘(有空则摞在空柱子上)。

    重复上述两步就可以得到答案。

    注意:这样得到的最后的答案不一定是摞在c上,如果N是偶数将摞在b上,所以如果N是偶数我们就令第二个柱子为c,第三个柱子为b,这样就一定最后是摞在c上的。

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

    真的有毒

  • 相关阅读:
    LeetCode15 3Sum
    LeetCode10 Regular Expression Matching
    LeetCode20 Valid Parentheses
    LeetCode21 Merge Two Sorted Lists
    LeetCode13 Roman to Integer
    LeetCode12 Integer to Roman
    LeetCode11 Container With Most Water
    LeetCode19 Remove Nth Node From End of List
    LeetCode14 Longest Common Prefix
    LeetCode9 Palindrome Number
  • 原文地址:https://www.cnblogs.com/WangBo020809/p/14643885.html
Copyright © 2011-2022 走看看