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

0.PTA得分截图

1.本周学习总结

1.1 总结栈和队列内容

栈的存储结构及操作

顺序栈:
DS博客作业02--栈和队列_第1张图片

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

//顺序栈的结构体
typedef struct 
{
    int data[MaxSize];
    int top;
}Stack;
tpyedef Stack *SqStack;

//链栈结构体
typedef struct Node
{
    char data;
    struct Node *next; 
} Node, *ListStack;
//顺序栈初始化
void InitStack (SqStack &S)
{
    S=new Stack;
    S->top=-1;
}

//链栈初始化
void InitStack (ListStack &S)
{
    S=new Node;
    S->next=NULL;
}
//顺序栈入栈
bool Push(SqStack &S,int e)
{
    if(栈满)return false;
    栈顶指针增1;
    元素e放在栈顶指针处;
}

//链栈入栈
void Push(LinkStack &S,int e)
{
    //链栈不考虑栈满
    新增结点p存放元素e;
    采用头插法将p结点插入;
}
//顺序栈出栈
bool Pop(SqStack &S,int &e)
{
    if(栈空)return false;
    取栈顶元素;
    栈顶指针减1;
}

//链栈出栈
bool Pop(LinkStack &S,int &e)
{
    if(栈空)return false;
    p指向头结点后一个元素;
    e存放该元素的值;
    删除该元素;
}
//顺序栈销毁
void DestroyStack(SqStack &S)
{
    delete S;
}

//链栈销毁
void DestroyStack(LinkStack &S)
{
    //链栈销毁涉及删除链的操作
    while(遍历链栈)
    {
        p=S->next;
        delete S;
        S=p;
    }
}
//C++模板类
stack  S;     //初始化链栈
S.push(x);    //元素x进栈
S.top();    //返回栈顶元素
S.pop();    //出栈;
S.empty();    //判断栈空,若空返回true
S.size();    //访问栈中元素个数

栈的应用

1.判断对称串

定义顺序栈;
将字符串入栈;
for(遍历字符串)
{
    出栈元素e;
    if(e!=当前串字符)
    {
        return false;
    }
    return true;
}

2.括号匹配

定义顺序栈;
while(遍历串)
{
   if(不是括号) 取下一个字符;
   else
   {
       if(左括号) 入栈;
       else if(右括号)
       {
            if(空栈)错误;
            if(匹配)出栈;
            else 错误;           
       }
    }   
) 
if (栈依然为空) 
    匹配正确;
else   
    错误;

3.中缀表达式转后缀表达式

定义栈;
输入字符串s;
for(遍历字符串)
{
    if(是数字、小数点、正负号)
    {
        输出,并判断下一个是否是数字或小数点;//若不是,则输出空格隔开两个数字
	continue;
    }
    if(出现右括号)
    {
        出栈输出,直到遇到左括号或栈空;
	continue;
    }
    if(栈空或者比栈顶符号优先级高)
    {
	入栈;
    }
    else
    {
	先出栈直到遇到左括号或者栈空,再入栈新符号;
    }
}
while(栈不空)
{
    出栈栈中剩余符号;
}

4.迷宫路径

将入口进栈;
mg[xi][yi]=-1;
while(栈不空)
{
    取栈顶方块;
    if(当前方块是出口)
    {
        输出路径;
        return true;
    }
    查找下一可走方块;
    if(找到相邻可走方块)
    {
        当前方块的坐标和方位进栈;
        mg[i][j]=-1;
    }
    if(没有找到相邻可走方块)
    {
        出栈方块;
        mg[i][j]=0;
    }
}
return false;

队列的存储结构及操作

顺序队:
DS博客作业02--栈和队列_第3张图片

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

//顺序队结构体定义
typedef struct 
{
    int data[MaxSize];
    int front,rear;
}queue;
typedef queue *SqQueue;

//链队结构体定义
typedef struct qnode
{
    int data;
    struct qnode *next;
}QNode,*QueuePtr;

typedef struct
{
    QueuePtr front;
    QueuePtr rear;
}LinkQueue;
//顺序队初始化
void InitQueue(SqQueue &q)
{
    q=new queue;
    q->front=q->rear=-1;
}

//链队初始化
void InitQueue(LinkQueue &q)
{
   q.front=q.rear=new QNode;
   q.front->next=NULL;
}
//顺序队入队
bool enQueue(SqQueue &q, int e)
{
    if(队满)    return false;
    队尾增1;
    rear位置插入元素e;
}

//链队入队
void enQueue(LinkQueue &q, int e)
{
    //不需要考虑队满
    新建结点p;
    e赋值给结点p;
    尾插法插入结点p;
}    
//顺序队出队
bool deQueue(SqQueue &q, int &e)
{
    if(队空) return false;
    队头增1;
    取对头元素赋值给e;
}

//链队出队
bool deQueue(LinkQueue &q, int &e)
{
    if(队空) return false;
    p指针指向队头后一个结点;
    取p结点元素赋值给e;
    删除结点p;
    if(队尾为p) q.rear=q.front;//只剩一个数据结点
    delete p;
}
//顺序队销毁
void DestroyQueue(SqQueue &q)
{
    delete q;
}

//链队销毁
void DestroyQueue(LinkQueue &q)
{
    while(q.front)
    {
        q.rear=q.front->next;
        delete q.front;
        q.front=q.rear;
    }
}
//C++模板类
queueq//初始化链队
q.push(e)    //元素e入队
q.front()    //访问队头元素
q.rear()    //访问队尾元素
q.pop()    //出队
q.empty()     //判断队列是否为空,为空返回true
q.size()    //访问队列长度
//循环队列初始化
q->front=q->rear=0;

//循环队列为空
q->front=q->rear;

//循环队列队满
(q->rear+1) % MaxSize=q->front;

//循环队列进队
q->rear=(q->rear+1) % MaxSize;

//循环队列出队
q->front=(q->front+1) % MaxSize;

队列应用

1.报数游戏(1出列 2站右)

n个人入队;
while(队列不空)
{
    出队一个元素e;
    if(队列不空)
    {
        出队一个元素e;
        刚出队的元素e再入队;
    }
}

2.迷宫路径

将入口入队;
mg[xi][yi]=-1;
while(队列q不空)
{
    出队方块e;
    if(e是出口) 
    {
        输出路径;
        return true;
    }
    for(对于方块e的所有可走方块e1)
    {
        将方块e1进队;
        mg[i][j]=-1;
    }
}
return false;

3.各类排队问题,如银行排队,舞会舞伴等。

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

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

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

  • 栈与队列是操作受限的线性表,栈只能从栈顶插入删除,栈是先进后出,队列只允许在表的一端插入,另一端删除元素,队列是先进先出。
  • 栈的优点:在需要按照保存数据的相反的顺序来使用数据时,就可以用到栈。比如:递归算法,递归算法用到的保存足迹和返回运算就是要靠栈来实现,逆序输出等。
  • 队列的优点:排队的应用,在模拟队列上的应用。
  • 顺序栈和链栈:顺序栈出栈不删除数据元素,链栈出栈是物理删除数据元素。顺序栈需要考虑栈满,链队则不需要考虑。链栈可以使用C++模板类。
  • 顺序队和链队:大体上与顺序栈和链栈相似,个别插入删除元素函数稍有不同。

2.PTA实验作业

2.1.题目1:表达式转换

2.1.1代码截图

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

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

2.1.2本题PTA提交列表说明。

1.编译错误:编译器未选择C++。

2.2 题目2:符号匹配

2.2.1代码截图

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

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

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

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

2.2.2本题PTA提交列表说明。

1.部分正确:缺右边情况答案错误。解决方法:在最后栈不空判断加入e = St.top();right = 1;
因为输入连续左括号时,如(((((,也是缺右边的一种情况。
2.部分正确:缺右边情况仍然错误。解决方法:栈不空且不匹配条件下加入语句e = St.top();
right = 1;因为出现不匹配,如[ ( ] ),也是符号’(‘缺右边的一种情况。
3.部分正确:数组b遍历到’/’或’/’时,造成当出现//,’’号被算两次,结果答案错误。解决方法:将两个if条件判断语句改成if ,else if语句防止第二个if条件成立。

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

3.1 题目及解题代码

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

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

3.1.1 该题的设计思路

建立一个临时的容器,模拟弹出过程,如果这个弹出的数字和栈顶数字是吻合的,那么栈就要把已有的数字弹出来。如果栈是空的,或者栈顶数字和弹出的数字不等,那么我们应该把pushed数字一直往里放,直到相等为止。如果临时容器最后是空,返回true;否则,返回false。

3.1.2 该题的伪代码

for i=0 to len do
{
    if(popped的元素等于res的元素)
        弹出res元素;
    else 
    {
        while(两个元素不相等)
        {
            pushed元素放入res中;
        }
    }
}

3.1.3 运行结果

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

  • 题中使用vector建立一个临时的容器,模拟题目的入栈出栈操作,没有新建栈进行模拟。
  • popped序列可能是随机的,第一个入栈元素可能在中途出栈,所以需要储存pushed序列,直到与popped元素相等出栈。
  • 如何表示和保存入栈和出栈序列是题目的关键。

3.2 题目及解题代码

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

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

3.2.1 该题的设计思路

先将输入的原始队列按照身高h递减、若h相同则以k递增的规则进行排序。然后从前往后遍历扫描一遍队列,并依据k进行插入。
递减h、递增k排列:

3.2.2 该题的伪代码

升高h降序排列;
if(h相等)  
    k升序排列;
while(遍历数组)
{
    按k排列每个人位置;
}

3.2.3 运行结果

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

  • 题目巧妙的按照递减h为主次序,递增k为赋次序进行排序,之后只需要遍历数组对每个k的值排列。
  • 先安排个子高的人,再安排个子矮的人,因为个子矮的人的插入不会对个子高的人的排序产生影响。
  • 首先要理解题目的意思,理解k的含义,确定如何排序才能使k的序列正确且不被其他元素插入而破坏。

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