DS博客作业02--栈和队列

0.PTA得分截图

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

1.1 总结栈和队列内容:

1.1.1 栈

  • 栈的定义:
    栈的本质还是线性表:限定仅在表尾进行插入或删除操作。 俗称:后进先出 ,也可说是先进后出。
    DS博客作业02--栈和队列_第1张图片
  • 栈的声明(栈的声明有两种):
    第一种:
typedef struct sta
{
    int stack[SIZE];    /* 存放栈中元素的一维数组 */
    int top;            /* 存放栈顶元素的下标 */
}stack;

第二种:

typedef struct sta
{
    int *top;            /* 栈顶指针 */
    int *bottom;        /* 栈底指针 */
    int stack_size;        /* 栈的最大容量 */
}stack;
  • 栈的分类:
    与线性表同样的,栈也分为顺序和链式两大类。其实和线性表大同小异,只不过限制在表尾进行操作的线性表的特殊表现形式。
  • 顺序栈:
    利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针 top 指示栈顶元素在顺序栈中的位置,附设指针 base 指示栈底的位置。 同样,应该采用可以动态增长存储容量的结构。且注意,如果栈已经空了,再继续出栈操作,则发生元素下溢,如果栈满了,再继续入栈操作,则发生元素上溢。栈底指针 base 初始为空,说明栈不存在,栈顶指针 top 初始指向 base,则说明栈空,元素入栈,则 top++,元素出栈,则 top--,故,栈顶指针指示的位置其实是栈顶元素的下一位(不是栈顶元素的位置)。
    DS博客作业02--栈和队列_第2张图片
  • 链式栈:
    其实就是链表的特殊情形,一个链表,带头结点,栈顶在表头,插入和删除(出栈和入栈)都在表头进行,也就是头插法建表和头删除元素的算法。显然,链栈还是插入删除的效率较高,且能共享存储空间。
    DS博客作业02--栈和队列_第3张图片
    是栈顶在表头!栈顶指针指向表头结点。栈底是链表的尾部,base 就是尾指针。还有,理论上,链式结构没有满这一说,但是理论上是这样的,也要结合具体的内存,操作系统等环境因素。
  • 栈的基本操作函数(仅针对顺序栈):
    • InitStack(&s):初始化栈。构造一个空栈s。
      函数实现:
void InitStack(SqStack &s)
{  s=new Stack;     
    s->top=-1;
} 
  • DestroyStack(&s):销毁栈。释放栈s占用的存储空间。
    函数实现:
void DestroyStack(SqStack &s)
{
  delete s;
}
  • StackEmpty(s):判断栈是否为空:若栈s为空,则返回真(1);否则返回假(0)。
    函数实现:
bool StackEmpty(SqStack s)
{
  return(s->top==-1);
}
  • Push(&S,e):进栈。将元素e插入到栈s中作为栈顶元素。
    函数实现:
bool Push(SqStack &s,ElemType e)
{
  if (s->top==MaxSize-1)  
    return false;
   s->top++;           //栈顶指针增1
   s->data[s->top]=e;     
   return true;
}
  • Pop(&s,&e):出栈。从栈s中退出栈顶元素,并将其值赋给e。
    函数实现:
bool Pop(SqStack &s,ElemType &e)
{
   if (s->top==-1)  //栈为空的情况,栈下溢出
    return false;
   e=s->data[s->top];//取栈顶指针元素     
   s->top--;        //栈顶指针减1
   return true;
}
  • GetTop(s,&e):取栈顶元素。返回当前的栈顶元素,并将其值赋给e。
    函数实现:
bool GetTop(SqStack *s,ElemType &e)
{   
   if (s->top==-1)  //栈为空的情况    
    return false;
    e=s->data[s->top];      
    return true;
}
  • 栈的头文件(C++):stack操作模板:
#include
1.stack  s:初始化栈,参数表示元素类型。//后续的函数引用你的初始化
2.s.push(t):入栈元素t。
3.s.top():返回栈顶元素。
4.s.pop():出栈操作只是删除栈顶元素,并不返回该元素。
5.s.empty(),当栈空时,返回true。
6.s.size():访问栈中的元素个数。
  • 栈的应用:
    • 字符匹配:在C语言中有一些符号是成对匹配出现的,利用栈可以实现类似编译器括号是否匹配的能力。
    • 小型计算器的实现:将中缀表达式转后缀表达式。
    • 十进制正整数N进制:进制转换可以用很多方法来实现,其中也能用栈的方式实现。

1.1.2 队列

  • 队列的定义:
    只允许在表的一端进行插入,而在表的另一端进行删除的线性表。
    DS博客作业02--栈和队列_第4张图片

  • 队列的声明:

struct QNode {
    ElementType *Data;  /* 存储元素的数组   */
    Position Front;     /* 队列的头指针     */
    int Count;          /* 队列中元素个数   */
    int MaxSize;        /* 队列最大容量     */
};
  • 队列的基本操作函数:
    • InitQueue(&Q):构造一个空队列Q。
      函数实现:
void InitQueue(SqQueue *&Q){  
    Q=(SqQueue *)malloc(sizeof(SqQueue));  
    Q->front=Q->rear=-1;  
}  
  • DestroyQueue(&Q):销毁队列Q。
    函数实现:
void DestroyQueue(SqQueue *&Q){  
    free(Q);  
}  
  • QueueEmpty(Q):判断队列Q是否为空。
    函数实现:
void QueueEmpty(SqQueue *Q){  
    return (Q->front==Q->rear);  
}  
  • EnQueue(&Q, e):插入元素e为Q的新的队尾元素。
    函数实现:
bool EnQueue(SqQueue *&Q,ElemType e){    
    if(Q->rear==MaxSize) return false;   //队满上溢   
    Q->rear++;    
    Q->data[Q->rear]=e;    
    return true;    
}   

DS博客作业02--栈和队列_第5张图片

  • DeQueue(&Q, &e):删除Q的队头元素,并用e返回其值。
    函数实现:
bool EeQueue(SqQueue *&Q,ElemType &e){  
    if(Q->front==Q->rear) return false;  
    Q->front++;  
    e=Q->data[Q->front];  
    return true;  
}  

DS博客作业02--栈和队列_第6张图片

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

学习了栈和队列,发现两个本质上都是线性表,两者的功能上相似的地方,也有不同的地方。它们都可以用线性表的顺序存储结构来实现,但都存在着顺序存储的一些弊端。
在对栈和队列的学习中,扩展了眼界,对一些题目有了新的理解,如线性表中6-8 jmu-ds-链表倒数第m个数,如果这题用栈或者队列来编译,将更容易,时间复杂度上将更低,这或许就是算法学习的意义:找到时间复杂度更低的算法来实现要求。
在对栈和队列的学习后,了解了日常网络中有很多的事情都是可以通过栈和队列实现的,例如网页的返回,就是通过可以栈来实现的。

2.PTA实验作业(0-2分)

2.1 7-6 jmu-报数游戏 (15分)

2.1.1 代码截图

DS博客作业02--栈和队列_第7张图片

2.1.2 本题PTA提交列表说明。

Q1:编译错误
A1:再次将C++按C提交
Q2:部分正确
A2:m>=n的点题目要求输出为error!但我输出为error

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

2.2.1 代码截图

DS博客作业02--栈和队列_第8张图片

2.2.2 本题PTA提交列表说明。

DS博客作业02--栈和队列_第9张图片

Q1:编译错误
A1:将C++按C提交
Q2:部分正确
A2:用了多个while导致运行超时
Q3:格式错误
A3:将while删除几个重新编译,但空格没掌握好
Q4:答案正确
A4:将空格处理了一下,虽然PTA对了,但我发现我自己输入3个数(两奇一偶)中最后一个偶数后还有空格
Q5:编译错误
A5:在上一个代码中加上if判断但用q.empty代码后没加小括号
Q6:部分正确
A6:加上一个限定条件后运行发现如果奇数数列不为空时,最后一个偶数和它之后的奇数键没有空格,所以我加在加上了判断奇数数列是否为空的条件,不仅PTA过了,我自己加的测试点也过了

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

3.1 题目及解题代码

DS博客作业02--栈和队列_第10张图片
解题代码:

class Solution {
public:
    bool canMeasureWater(int x, int y, int z) {
        // assumed if z = a * x  + b * y, then return true; otherwise, gives false
        // if x = t1 * __gcd(x,y), y = t2 * __gcd(x,y);
        // z = __gcd(x,y) *  (a * t1 + b * t2) ==> z % __gcd != 0 ==> false
        // x = 3, y = 5, z = 4  ===> z = -1 * x + 2 * y
        // x = 2, y = 6, z = 5  ===> failed
        if (z < 0 || x + y < z) return false;
        if (x == z || y == z || x + y == z) return true;
        return z % __gcd(x, y) == 0; 
    
    }
};

3.1.1 该题的设计思路

将本问题转化为ax+by=z是否有解,
定理:a b x y 均为整数,如果ax+by=z有解,那么z一定是gcd(a,b)的倍数,否则无解。//gcd(a,b)函数为求a和b的公约数的函数
时间复杂度为:O(log(min(x,y)),取决于计算最大公约数所使用的辗转相除法。
空间复杂度为:O(1)

3.1.2 该题的伪代码

if z小于0或者x+y小于z then
   返回false
if x等于z或y等于z或x+y等于z then
   返回true
返回 z是否对x和y的公约数的倍数//即是返回true,否返回false

3.1.3运行结果

DS博客作业02--栈和队列_第11张图片

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

解题优势:该题的设计思路通俗易懂,但凡有点数学基础都能立马通过该解题思路理解复杂的题干要求,在计算最大公约数小的情况加该题的时间复杂度会相对更低。
难点:如果没想到求z和x,y最大公约数的关系,将会不容易下手,并且可能会陷入僵局。计算最大公约数所使用的辗转相除法大的话,时间复杂度相应增大。

3.2 题目及解题代码

DS博客作业02--栈和队列_第12张图片

解题代码:

class Solution {
public:
    bool validateStackSequences(vector& pushed, vector& popped) {
        stack st;
        int n = popped.size();
        int j = 0;
        for (int i = 0; i < pushed.size(); ++i){
            st.push(pushed[i]);
            while(!st.empty() && j < n && st.top() == popped[j]){
                st.pop();
                ++j;
            }
        }
        return st.empty();
    }
};

3.2.1 该题的设计思路

尝试按照 popped 中的顺序模拟一下出栈操作,如果符合则返回 true,否则返回 false。这里用到的贪心法则是如果栈顶元素等于 popped 序列中下一个要 pop 的值,则应立刻将该值 pop 出来。
使用一个栈 st 来模拟该操作。将 pushed 数组中的每个数依次入栈,同时判断这个数是不是 popped 数组中下一个要 pop 的值,如果是就把它 pop 出来。最后检查栈是否为空。
时间复杂度:O(N)。将所以元素一遍入栈,一遍出栈,需要 O(2N)。
空间复杂度:O(N)。使用了辅助栈 st。

3.2.2 该题的伪代码

初始化栈st
定义n并赋值要出栈的数量
定义j并赋值0
for 定义i从0到要入栈的数量,完成循环后对i前缀递增
    将push[i]入栈st
    while st栈不为空并且j小于n并且st栈顶等于pop[j]
        将st栈顶出栈
        对j前缀递增
    end while
end for
return 判断st栈是否为空的结果

3.2.3 运行结果

DS博客作业02--栈和队列_第13张图片
DS博客作业02--栈和队列_第14张图片

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

解题优势:思路简单清晰:直接对题目的条件来一边入栈出栈的操作,在调试时更好地去调试。
难点:时间复杂度和空间复杂度上欠缺,对题目所给的条件设计入栈出栈操作时的循环条件不便于掌控。

你可能感兴趣的:(DS博客作业02--栈和队列)