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

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

    0.PTA得分截图

    1.本周学习总结

    1.1 栈

    • 顺序栈:用一段连续的存储空间来存储栈中的数据元素,比较常见的是用数组来实现顺序栈

    栈的声明

    typedef struct sta
     {
         int *top;            /* 栈顶指针 */
         int *bottom;        /* 栈底指针 */
         int stack_size;        /* 栈的最大容量 */
     }stack;
    

    栈的初始化

      stack InitStack (stack p)
      {
          p.bottom = (int *)malloc(p.stack_size * sizeof(int));
          if (p.bottom == NULL)
          {
              printf("初始化栈失败
    ");
              exit(0);
          }
         p.top = p.bottom;
         p.stack_size = MAX_SIZE;
     
         return p;
     }
    

    入栈

    stack Push (stack p)
      {
          int data;
          if (StackFull(p) == Full)
          {
              printf("栈空间已满,无法入栈");
              return p;
          }
         printf("Please input data");
         scanf("%d", &data);
         *p.top = data;
         p.top++;
     
         return p;
      }
    

    出栈

    stack Pop (stack p)
     {
         if (StackEmpty(p) == Empty)
         {
             printf("栈为空栈,无法出栈 ");
             return p;
         }
         p.top--;
         printf("出栈元素为:%d
    ", *p.top);
     
         return p;
     }
    

    判断栈是否为空

    int StackEmpty (stack p)
     {
         if (p.top == p.bottom)
         {
             return Empty;
         }
         else
         {
             return Avail;
         }
     }
    

    判断栈是否为满

    int StackFull (stack p)
     {
         if (p.top - p.bottom == p.stack_size)
         {
             return Full;
         }
         else
         {
             return Avail;
         }
     }
    

    遍历栈中的元素

    void DisplyStack (stack p)
     {
         if (StackEmpty(p) == Empty)
         {
             printf("栈为空栈,无法遍历
    ");
             return;
         }
         printf("栈中元素为:");
         printf("顶端[");
         while (p.top != p.bottom)
         {
             p.top--;
             printf("%d-", *p.top);
         }
         printf("]底端
    ");
     }
    
    • 链栈:链式栈中的元素以Node的形式存储,节点Node中存有此节点存于栈中的元素以及指向下个节点的指针

    栈的声明

    typedef struct node 
    {
    	SElemType  data;//数据域
    	struct node *next;//指针域
    }LinkStackNode;
    

    入栈

    Status Push(LinkStackNode *top, SElemType x) 
    {
    	LinkStackNode * p;
    	p = (LinkStackNode *)malloc(sizeof(LinkStackNode));
    	if (!p)  return ERROR;    
    	p->data = x;
    	p->next = top->next;
    	top->next = p;    
    	return OK;
    }
    

    出栈

    Status Pop(LinkStackNode *top, SElemType *x)
    {  
    	LinkStackNode * p;
    	p = top->next;
    	if (p == NULL)   
    		return OVERFLOW;
    	top->next = p->next;
    	*x = p->data;
    	free(p);    
    	return OK;
    }
    

    1.2 栈的应用

    • 数制转换

    十进制数N和其他d进制数的转换是计算机实现计算的基本问题,其解决方法很多,同样用栈也可以解决
    下述算法实现了十进制数转八进制数,并打印结果

    public class Conversion 
    {
        public static void conversion(int N) 
        {
            ArrayStack<Integer> stack = new ArrayStack<>();
            while (N != 0) 
            {
                stack.push(N % 8);
                N /= 8;
            }
            while (!stack.isEmpty()) 
            {
                System.out.print(stack.pop());
            }
        }
    
        public static void main(String[] args) 
        {
            conversion(2007);
        }
    }
    
    
    • 括号匹配检验

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

    public class Match 
    {
        public static boolean match(String s) 
        {
            ArrayStack<Character> stack = new ArrayStack<>();
            for (int i = 0; i < s.length(); i++) 
            {
                char c = s.charAt(i);
                switch (c) 
                {
                case ')':
                    if (!stack.isEmpty() && stack.pop() == '(') 
                    {
                        break;
                    }
                    else 
                    {
                        return false;
                    }
                case ']':
                    if (!stack.isEmpty() && stack.pop() == '[')
                    {
                        break;
                    }
                    else 
                    {
                        return false;
                    }
                case '}':
                    if (!stack.isEmpty() && stack.pop() == '{') 
                    {
                        break;
                    }
                    else 
                    {
                        return false;
                    }
                default:
                    stack.push(c);
                    break;
                }
            }
            return stack.isEmpty();
        }
    
        public static void main(String[] args)  
        {
            System.out.println(match("{[()]()[{}]}"));
            System.out.println(match("{[()]}}"));
        }
    }
    
    • 迷宫求解

    求迷宫从入口到出口的所有路径是一个经典的程序设计问题。由于计算机解迷宫时,通常用的是“穷举求解”的方法,即从入口出发,顺某一方向向前探索,若能走通,则继续往前走;否则沿原路退回,换一个方向再继续探索,直至所有可能的通路都探索到为止。
    为了保证在任何位置都能沿原路退回,显然需要用一个后进先出的结构来保存从入口到当前位置的路径。因此在迷宫求解时应用“栈”也就是自然而然的事情了。
    在计算机中,我们可以用一个二维数组来表示一个迷宫
    求解迷宫的算法思想的伪代码

    初始化,将起点加入堆栈;
    while(堆栈不为空)
    {
        取出栈顶位置为当前位置;
        如果 当前位置是终点,
        则 使用堆栈记录的路径标记从起点至终点的路径;
        否则
        {
            按照从下、右、上、左的顺序将当前位置下一个可以探索的位置入栈;
            如果 当前位置的四周均不通
            则 当前位置出栈;
        }
    }
    
    

    1.3 队列

    • 顺序队列:队列的这种头尾相接的顺序存储结构称为循环队列。

    队列声明

    #define MAXSIZE  5    //最大容量是5个元素
    struct queue   //队列
    
    {
           int a[MAXSIZE];   //队列元素
           int front;          //队头
           int rear;           //队尾
    };
    

    判断循环队列是否为空

    int SeQueue::Empty()
    { 
    if(rear==front) return(1);
    else return(0);
    }
    

    在循环队列中插入新的元素x

    void SeQueue::AddQ(ElemType x)
    {
    	if ((rear + 1) % MAXSIZE == front)
    		cout << " QUEUE IS FULL! " << endl;
    	else
    	{
    		rear = (rear + 1) % MAXSIZE;
    		elem[rear] = x;
    		cout << " OK!";
    	}
    }
    

    删除队列中队首元素

    ElemType SeQueue::DelQ()
    {
    	if (front == rear)
    	{
    		cout << " QUEUE IS EMPTY! " << endl; return -1;
    	}
    	else 
    	{
    		front = (front + 1) % MAXSIZE;
    		return(elem[front]);
    	}
    }
    

    取队列中的队首元素

    ElemType SeQueue::Front()
    {
    	ElemType x;
    	if (front == rear)
    		cout << "QUEUE IS EMPTY " << endl;
    	else 
    		x = elem[(front + 1) % MAXSIZE];
    	return (x);
    }
    
    • 环形队列:

    队列声明

    typedef struct
    {
    	ElemType data[Max]; 
    	int front;   
    	int count;   
    }QueueType;
    

    初始化队列

    void InitQueue(QueueType *&q)
    {
    	q = (QueueType *)malloc(sizeof(QueueType));
    	q->front =0;
    	q->count =0;
    }
    

    判断队列是否为空

    void  EmptyQueue(QueueType *q)
    {
    	if (q->count==0)
    		cout<< "队列为空!" << endl;
    	else
    		cout << "队列不为空!" << endl;
    }
    

    元素进队

    int enQueue(QueueType*& q, ElemType x)
    {
    	int rear;
    	if (q->count == Max) //队满溢出
    		return 0;
    	else
    	{
    		rear = (q->front + q->count) % Max;
    		rear = (rear + 1) % Max;
    		q->data[rear] = x;
    		q->count++;
    		return 1;
    	}
    }
    

    元素出队

    int deQueue(QueueType *&q,ElemType &x)
    {
    	if(q->count==0)
    		return 0;
    	else
    	{
    		q->front=(q->front+1)%Max;
    		x=q->data[q->front];
    		q->count--; 
    	}
    }
    

    输出队列的元素个数

    void LenghtQueue(QueueType *q)
    {
    	cout << q->count << endl;
    }
    

    释放队列

    void DestroyQueue(QueueType *q)
    {
    	free(q);
    }
    
    • 链队列:

    队列声明

    typedef struct QNode
    {
        int data;
        struct QNode * next;
    }QNode;
    

    创建队列

    QNode* initQueue() 
    {
        QNode* queue = (QNode*)malloc(sizeof(QNode));
        queue->next = NULL;
        return queue;
    }
    

    入队

    QNode* enQueue(QNode* rear, int data) 
    {
        QNode* enElem = (QNode*)malloc(sizeof(QNode));
        enElem->data = data;
        enElem->next = NULL;
        rear->next = enElem;
        rear = enElem;
        return rear;
    }
    

    出队

    void DeQueue(QNode* top, QNode* rear)
    {
        if (top->next == NULL) 
        {
            printf("队列为空");
            return;
        }
    
        QNode* p = top->next;
        printf("%d", p->data);
        top->next = p->next;
        if (rear == p) 
        {
            rear = top;
        }
        free(p);
    }
    
    • 队列应用

    2.PTA实验作业

    • 代码上传码云没整明白,所以还是截图代码了,下次一定整明白

    2.1 符号配对

    2.1.1 解题思路及伪代码

    解题思路:把比较特殊的//用< >代替,创建一个栈然后把找到的对应符号放入栈中,然后进行比较得到符号是否匹配

    int main
    {
      static char ch1[1000], ch2[1000], ch[10000];//ch放代码,ch2放找到的符号,ch1用于符号匹配
    for(i = 0;; i++)
      {
        找到对应符号然后放入ch2中//用<>代替两个的符号
      }
    int flag=1 用于记录
    for (i = 0; i < k; i++)
      {
        if ch2中符号是左符号,放入栈中
        else if ch2中符号是右符号
        {
          if 栈中存在符号,并且和ch2和栈中符号匹配,则消除栈中该符号
          else 输出NO 和对应缺少的符号,flag=0
        }
      }
    if flag=1同时栈中无符号 输出YES
    else
      {  输出  NO
         根据栈中情况输出对应缺少符号
      }
    }
    

    2.1.2 总结解题所用的知识点

    栈的出栈和入栈,栈指针的变化来判断栈中元素变化

    2.2 银行业务队列简单模拟

    2.2.1 解题思路及伪代码

    解题思路:依题意得A总比B先输出,且当A中含有元素时总先输出两个,所以按照2:1的比例输出AB中的数,用队列来表示就是出队操作

    int main
    {
    struct queue QA, QB;//创建两个队列
    Createqueue(&QA);
    Createqueue(&QB);
    
    scanf("%d", &n);
    for (i = 0; i < n; i++)
    {
      if是奇数 放入队列QA  
      else 放入队列QB
    }
    while 两个队列不同时为空
    {
      if QA不为空 输出QA中的数,同时出队
      if QA不为空 输出QA中的数,同时出队
      if QB不为空 输出QB中的数,同时出队
    }
    

    2.2.2 总结解题所用的知识点

    队列的出队和入队

    3.阅读代码

    3.1 题目及解题代码

    解题代码

    class Solution:
        def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
            stack, i = [], 0
            for num in pushed:
                stack.append(num) # num 入栈
                while stack and stack[-1] == popped[i]: # 循环判断与出栈
                    stack.pop()
                    i += 1
            return not stack
    

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


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

    由于题目规定 栈的所有数字均不相等 ,因此在循环入栈中,每个元素出栈的位置的可能性是唯一的(若有重复数字,则具有多个可出栈的位置)。因而,在遇到 “栈顶元素 == 弹出序列的当前元素” 就应立即执行出栈。
    先找到进栈中最后一个(我叫做标准值),在出栈之后的的所有元素,都只会在这个值后面。所以在出栈数列中最后一个进栈的数字后面一定是递减的。可以来排个序。对于这个标准值前面的数字呢?如果说前一个数字比后一个数字小没什么关系,但是如果说前面数字比后面数字大就要讨论一下了。
    就拿[0,1,2,3,4,5,..,12]和[0,4,3,5,2,1,7,8,10,11,9,6]看这个地方有个5,比后面的2要大。我们已经看到0,3,4已经出栈了。那么现在栈呢剩下的就是[1,2]我们不能选1,中间隔着2,所以我们要选择离5更近的一个数字。后面11比9大,这个时候栈内还有[6,9]选择离11更接近的9,最后就是剩下的6。

  • 相关阅读:
    JSOI2015 总结
    JSOI2014 总结
    JSOI2010/2011 总结
    1.13 考试总结
    1.15 考试总结
    [SDOI2015]寻宝游戏
    [教程]视频网课如何打开倍速纵享丝滑
    对机器学习的一些理解【学术篇】
    angular JS 路由功能
    理解 $scope
  • 原文地址:https://www.cnblogs.com/miao-witch/p/14619622.html
Copyright © 2011-2022 走看看