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

0.PTA得分截图

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

1.1 总结栈和队列内容

栈的存储结构及操作

栈是一种只能在一端进行插入或删除操作的线性表,只能在栈顶进行删除插入操作,是一种先进后出的线性表

typedef struct Stack
{
       ElementType *Data;       //存储元素的数组
       int top;                 //栈顶指针
}LStsck,*Stack;

栈的操作

大致代码:

栈空条件: top=-1
栈满条件: top=MaxSize-1
进栈e操作:top++; st->data[top]=e
退栈操作: e=st->data[top]; top--;

栈的应用

网络浏览器的浏览记录:用户访问一个新页面,其前一个页面地址会被存放至栈顶,即执行入栈操作;而“后退”按钮,即可沿相反的次序访问此前刚访问过的页面,即执行出栈操作
还有我们学的递归算法,每一次递归都将结果入栈,而后又执行出栈操作,最后得到结果
还有在课堂派里的进制转换,如十进制转为八进制等等,都是先将取余的的数保存进栈中,直到为零时出栈
表达式转换,符号配对,迷宫问题等等

队列的存储结构及操作

队列的存储结构

typedef struct Queue
{
     ElementType *Data;//存储元素的数组
     int rear,front;//队头队尾指针
}SQueue,*Queue;

操作

大致代码如下

//进队列
int EnQueue(SqQueue& Q, Person e)//加入队列,变换尾指针
{
	if (Q->rear == MAXQSIZE) return ERROR;//判断栈是否满
	Q->data[Q->rear] = e;
	Q->rear++;
	return OK;
}
//出队列
int DeQueue(SqQueue& Q, Person& e)//出队列,变换头指针
{
	if (Q->front == Q->rear) return ERROR;//判断栈是否空
	e = Q->data[Q->front];
	Q->front++;
	return OK;
}

队列应用

银行排队,以及银行排队的一系列扩展
搭配舞伴问题
还有就是用栈只能找到一条路径的迷宫问题,用队列可以找到多条问题

stack和queue

stack模板类的定义在头文件中
stack是链栈,不是顺序栈

stack的基本操作有:

入栈,s1.push(x);

出栈,s1.pop();//出栈操作只是删除栈顶元素,并不返回该元素。

访问栈顶,如例:s1.top()//并不删除该元素

判断栈空,如例:s1.empty()//当栈空时,返回true。

访问栈中的元素个数,如例:s1.size()

queue模板类的定义在头文件中
queue是链队列,不是顺序队列

queue的基本操作有:
入队,如例:q1.push(x); 将x接到队列的末端。

出队,如例:q1.pop(); 弹出队列的第一个元素,并不会返回被弹出元素的值。

访问队首元素,如例:q1.front(),即最早被压入队列的元素。

访问队尾元素,如例:q1.back(),即最后被压入队列的元素。

判断队列空,如例:q1.empty(),当队列空时,返回true。

访问队列中的元素个数,q1.size()

循环队列

如图所示,不可以继续添加元素,否则会造成数组越界而遭致程序出错。然而此时又不应该扩充数组,因为还有大量实际空间未被占用。
我们将其实现为循环队列,则很好解决了这个问题
图解如下:

当添加一个元素时,(rear+1)%MAXQSIZE;
当删除一个元素时,(front+1)%MAXQSIZE;
队满时:(Q.rear+1)%MAXSIZE==Q.front
队空时:Q.rear==Q.front

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

学习了栈和队列,相比之下还是要好理解一些,操作也更简单一些,主要是有一些库来更好操作,除了有一些难一点的题

这应该就完了线性结构,接下来的非线性结构应该就会更难一些了,得好好加油了!!!

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

2.1.题目1:题目名称

7-4 符号配对 (20分)
请编写程序检查C语言源程序中下列符号是否配对:/*与*/、(与)、[与]、{与}。

2.1.1代码截图

2.1.2本题PTA提交列表说明。

部分正确:开头有多余左符号,末尾没加判断栈为空的情况
部分正确:左右符号个数相同,达到最大值,但不匹配;这个我也不知道是啥,试了一下午,都不知道是啥子情况

2.2.题目1:题目名称

7-5 表达式转换 (25分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。

2.2.1代码截图

2.1.2本题PTA提交列表说明

部分正确:输出时没有将各个符号分开,导致格式错误。以及没有考虑到小数负数的情况,将正负号分别考虑,小数分别考虑就解决了这些问题
部分正确:修改后,显示的负数以及嵌套括号的情况显示错误;而在编译器时,我尝试过多种情况,并没有错误,后面我也会花点时间去解决它,看看是哪里的问题

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

3.1 题目及解题代码

题目:

请设计一个栈,除了常规栈支持的pop与push函数以外,还支持min函数,该函数返回栈元素中的最小值。执行push、pop和min操作的时间复杂度必须为O(1)。

解题代码:

3.1.1 该题的设计思路

算法时间复杂度O(1)
空间复杂度O(N)

3.1.2 该题的伪代码

void push(stack<int> Stack)
{
     输入入栈元素x;
     if(min>=x)
        判断栈空 
           将最小值min入栈
        将入栈元素x入栈
     else 将入栈元素x入栈
}
bool pop(stack<int> Stack)
{
     判断栈空
     if 栈内元素只有一个
        则将最小值= INT_MAX
     else if判断最小值是否为栈顶
             出栈顶,将最小值等于下一个栈顶
     去掉下一个栈顶,即第二小的值
}

3.1.3 运行结果

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

第一次看到这个题目时,觉得挺简单,但仔细想了想,要在完成题目要求时间复杂度为o(1)的条件下,确实不简单

他解题的优点恰恰是它本题的难点,用栈将它的顺序间接连接起来。

即在最小值的下一个地方放入第二小的值,第二小的值的下一个位置放入第三小的值,以此类推。就解决了o(1)的问题

3.2 题目及解题代码

给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
注意:
nums1和nums2中所有元素是唯一的。
nums1和nums2 的数组大小都不超过1000。

解题代码:

3.2.1 该题的设计思路

算法时间复杂度O(N)
空间复杂度O(N)

3.2.2 该题的伪代码

void DealStack(int nums1[MaxSize], int nums2[MaxSize])//构建栈来处理
{
    初始化哈希数组为0;
    for遍历nums2
       if 栈空或nums2[i]小于栈顶时,将nums2[i]入栈
       if nums2[i]大于栈顶时
           while(nums2[i]大于栈顶)
                写入哈希数组中
           将nums2[i]入栈
    剩下栈中还有值,全部赋值-1
    遍历nums1得出答案
}

3.2.3 运行结果

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

用以前的数组做的话,复杂度就是n2
而这题用了栈的写法,还结合了哈希数组,大大降低了时间
难点就是难想到用栈的做法,非常巧妙。我做的话肯定就是用暴力来做了
原文地址:https://www.cnblogs.com/200157zy/p/12536519.html