DS博客作业02--栈和队列
| 这个作业属于哪个班级 | 数据结构--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | DS博客作业02--栈和队列 |
| 这个作业的目标 | 学习栈和队列的结构设计及运算操作 |
| 姓名 | 黄抒鸿 |
0.PTA得分截图

1.本周学习总结
1.1 栈
1.1.1画一个栈的图形:

栈--又称“后进先出”的线性表。
栈顶(TOP)--允许插入和删除的一端。
栈底(bottom)--不允许插入和删除的一端。
空栈--表中没有元素。
栈中元素的特性:
具有线性关系;后进先出。
栈的进栈出栈规则:
栈顶出栈->栈底最后出栈;
时进时出->元素未完全进栈时,即可出栈。
栈的几种基本运算如下:
1.InitStack(&s):初始化栈。构造一个空栈s。
2.DestroyStack(&s):销毁栈。释放s占用的存储空间。
3.StackEmpty(s):判断栈是否为空;若空,则返回真,否则返回假。
4.Push(&s,e):进栈。将元素e插入到栈s中作为栈顶元素。
5.Pop(&s,e):出栈。从栈s中退出栈顶元素,并将其值赋值给e。
6.GetTop(s,&e):取栈顶元素。返回当前的栈顶元素,并将其值赋值给e。
1.1.2顺序栈的结构、操作函数
顺序栈模型示意图:

假设栈的元素个数最大不超过正整数MaxSize,所有的元素都具有同一数据类型ElemType,则栈类型SqStack:
typedef struct
{
ElemType data[MaxSize];
int top; //栈顶指针
}Stack;
typedef Stack *SqStack;
顺序栈4要素:
·栈空条件:top=-1
·栈满条件:top=MaxSize-1
·进栈e操作:top++;st->data[top]=e
·退栈操作:e=st->data[top];top--;
基本运算
1)初始化栈InitStack(&s)
void InitStack(SqStack &s)
{
s=new Stack;
s->top=-1;
}
2)销毁栈ClearStack(&s)
void DestroyStack(SqStack &s)
{
delete s;
}
3)判断栈是否为空StackEmpty(s)
bool StackEmpty(SqStack s)
{
return (s->top==-1);
}
4)进栈Push(&s,e)
bool Push(SqStack &S,ElemType e)
{
if(s->top==MaxSize-1)
return false;
s->top++;//栈顶指针+1
s->data[s->top]=e;
return true;
}
5)出栈Pop(&s,&e)
bool Pop(SqStack &s,ElemType &e)
{
if(s->top==-1) //栈为空的情况,栈下溢出
return false;
e=s->data[s->top];//取栈顶指针元素
s->top--; //栈顶指针-1
return true;
}
6)取栈顶元素GetTop(s)
bool GetTop(SqStack *s,ElemType &e)
{
if(s->top==1)//栈为空的情况
return false;
e=s->data[s->top];
return true;
}
1.1.3链栈的结构、操作函数
链栈模型示意图

链栈中数据节点类型LiStack定义如下:
typedef int ElemType;
typedef struct linknode
{
ElemType data;//数据域
struct linknode *next;//指针域
}LiNode,*LiStack;
链栈4要素:
·栈空条件:s->next=NULL
·栈满条件:不考虑
·进栈e操作:结点插入到头结点后,链表头插法
·退栈操作:取出头结点之后的结点元素并删除之
基本运算
1)初始化栈InitStack(&s)
void InitStack(LiStack &s)
{
s=new LiNode;
s->next=NULL;
}
2)销毁栈ClearStack(&s)
void DestroyStack(LiStack &s)
{
LiStack node;
while(s!=NULL)
{
node=s;
s=s->next;
delete node;
}
}
3)判断栈是否为空StackEmpty(s)
bool StackEmpty(LiStack s)
{
return (s->next==NULL);
}
4)进栈Push(&s,e)
void Push(LiStack &S,ElemType e)
{
LiStack p;
p=new LiNode;
p->data=e;
p->next=s->next;
s->next=p;
}
5)出栈Pop(&s,&e)
bool Pop(LiStack &s,ElemType &e)
{
LiStack p;
if(s->next==NULL) //栈空的情况
return false;
p=s->next;//p指向开始节点
e=p->data;
s->next=p->next;//删除*p节点
delete p;//释放*p节点
return true;
}
6)取栈顶元素GetTop(s)
bool GetTop(LiStack *s,ElemType &e)
{
if(s->next==NULL)//栈为空的情况
return false;
e=s->next->data;
return true;
}
1.2 栈的应用
表达式求值
中缀表达式:运算符号位于两个运算数之间。如:a+bc-d/e
后缀表达式:运算符号位于两个运算数之后。如:abc+de/-
中缀如何转后缀表达式:
1.优先级比栈顶运算符高入栈
2.低或相等,一直出栈到栈顶为空或者更高,写入后缀表达式
eg.表达式:(56-20)/(4+2)转为后缀表达式56#20#-4#2#+/
解析:“(”进栈,“-”进栈,“)”进栈,配对成功,“-”出栈;“/”进栈,“(”进栈,“+”进栈,“)”进栈,配对成功,“+”出栈;“/”还在栈底,“/”出栈。
1.3 队列
1.3.1画一个队列的图形:

队列:只允许在表的一端进行插入,而在表的另一端进行删除的线性表。
队尾(rear):允许插入的一端
队头(front):允许删除的一端
队列特点:先进先出
基本运算
1.InitQueue(&q):初始化队列。构造一个空队列q。
2.DesttroyQueue(&q):销毁队列。释放队列q占用的储存空间。
3.QueueEmpty(q):判断队列是否为空。若队列q为空,则返回真;否则返回假。
4.enQueue(&q,e):进队列。将元素e进队作为队尾元素。
5.deQueue(&q,&e):出队列。从队列q中出队一个元素,并将其值赋值给e。
1.3.2顺序队列的结构、操作函数
需要定义两个指针(top 和 rear)分别用于指向顺序队列中的队头元素和队尾元素:

结构定义:
typedef struct
{
ElemType data[MaxSize];
int front,rear; //队首和队尾指针
}Queue;
typedef Queue *SeQueue;
顺序队的四要素
·队空条件:front=rear
·队满条件:rear=MaxSize-1
·元素e进队:rear++;data[rear]=e;
·元素e出队:front++;e=data[front];
基本运算
1)初始化队列:InitQueue(&q)
void InitQueue(SqQueue &q)
{
q=new Queue;
q->front=q->rear=-1;
}
2)销毁队列DestroyQueue(q)
void DestroyQueue(SqQueue &q)
{
delete q;
}
3)判断队列是否为空QueueEmpty(q)
bool QueueEmpty(SqQueue q)
{
return(q->front==q->rear);
}
4)进队列enQueue(q,e)
bool enQueue(SqQueue &q,ElemType e)
{
if(q->rear+1==MaxSize)
return false; //队满上溢出
q->rear=q->rear+1;
q->data[q->rear]=e;
rerurn true;
}
5)出队列deQueue(q,e)
bool deQueue(SqQueue &q,ElemType &e)
{
if(q->front==q->rear)//队空下溢出
return false;
q->front=q->front-1;
e=q->data[q->front];
return true;
}
1.3.3环形队列的结构、操作函数

环形队列 结构体:
typedef struct
{
ElemType data[MaxSize];
int front,rear;
}Queue;
typedef Queue *SqQueue;
环形队列采用rear==MaxSize-1作为队满条件,当队满条件为真时,队中可能还有若干个空位置,这种溢出称为假溢出。
基本运算
1)初始化队列
void InitQueue(SqQueue &q)
{
q=new Queue;
q->front=q->rear=0;
}
2)进环形队列
bool enQueue(SqQueue &q,Elemtype e)
{
if((q->rear+1)%MaxSize==q->front)//队满上溢出
return false;
q->rear=(q->rear+1)%MaxSize;//移动rear
q->data[q->rear]=e;
return true;
}
3)出环形队列
bool deQueue(SqQueue &q,Elemtype e)
{
if(q->front==q->rear)//队空下溢出
return false
e=q->data[q->front];
q->front=(q->front+1)%MaxSize;//移动front
return true;
}
*销毁队列&判断队列是否为空 同顺序队列操作相同。
1.3.4链队列的结构、操作函数
链式队列的实现思想同顺序队列类似,只需创建两个指针分别指向链表中队列的队头元素和队尾元素:

链队中头尾指针类型LinkQueue定义:
typedef struct
{
QNode *front;
QNode *rear;
}LinkQueue;
链队的4要素
·队空条件:front=rear=NULL
·队满条件:不考虑
·进队e操作:将包含e的节点插入到单链表表尾
·出队操作:删除单链表首数据节点
基本运算
1)初始化链队列
void InitQueue(LinkQuNode &q)
{
q=new LinkQuNode;
q->front=q->rear=NULL;
}
2)进队列
bool enQueue(LinkQuNode &q,ElemType e)
{
p=new QNode;
p->data=e;//新建结点
p->next=NULL;//避免后面无结束
q->rear->next=p;
q->rear=p;//尾指针移动
}
3)出队列
bool deQueue(LinkQuNode &q,ElemType e)
{
Node t;
if(q->rear==NULL)
return false;
t=q->front;
if(q->front==q->rear)//此时只有一个数据
{
q->front=q->rear=NULL;
}
else
{
q->front=q->front->next;//移动front
}
e=t->data;
delete t;//删除
}
1.3.5队列应用。
操作系统
售票系统
打印机
手机短信发送
2.PTA实验作业
7-2 jmu-ds-符号配对
7-6 银行业务队列简单模拟
2.1 符号配对
2.1.1 解题思路及伪代码
解题思路:将字符一个一个处理,发现一个要处理的左符号“[,(,{”就入栈,发现一个需要处理的右符号“],),}”就与栈顶对比,如果是对应的左符号,那么把栈顶弹出,否则说明这个右符号不能配对,输出NO等信息并退出。如果一直处理到程序结尾都没有退出就是YES。
2.1.2 总结解题所用的知识点
本题需要考虑到左符号剩余,右符号剩余,配对情况,不配对情况,需要多重if 来进行约束判断。
伪代码:
定义字符型数组s
输入s
for(循环i=0 to i<len)
{
if(不是符号 )
跳过以下语句
if(为左符号 )进栈
else if(为右符号)
{
if( 栈空) 退出程序
else if(为右符号且配对) 出栈
}
} 结束for循环
//判断是否配对成功
if(栈空且i=len) 配对成功,输出“yes”
else if(i不等于len) 配对失败,输出“no”以及栈顶(栈为空不输出)
2.2 银行业务队列简单模拟
2.2.1 解题思路及伪代码
解题思路:这道题的意思就是模拟队列,将偶数的数字存到b窗口,将奇数的数字存到a窗口,而且是先进先出,所以可以采用队列,将偶数的放在b队列,将奇数的放在a队列;然后每输出两个a队列中的元素,再输出一个b队列中的元素;
伪代码:
queue<int> oddQu, evenQu;//定义两个队列
int N,i=0,num,evenLength,oddLength;
cin >> N;
while(i<N)
{
输入num;
if(num为偶数) 放在队列evenQu;
else (num为奇数) 放在队列oddQu;
}
。。。
2.2.2 总结解题所用的知识点
queue相关函数的使用、本题需要考虑a队列其个数以及奇偶性。
3.阅读代码(
3.1 题目及解题代码


class MyCircularQueue {
private:
int *data;
int front, rear;
int len;
public:
MyCircularQueue(int k) {
data = new int[k];
front = rear = -1;
len = k;
}
~MyCircularQueue() {
delete[] data;
}
bool enQueue(int value) {
if (isFull())
return false;
if (isEmpty())
front++;
rear = (rear + 1) % len;//rear后移一位,若到最后则转到数组头部
data[rear] = value;
return true;
}
bool deQueue() {
if (isEmpty())
return false;
if (front == rear && front != -1)//只剩一位
front = rear = -1;
else
front = (front + 1) % len;
return true;
}
int Front() {
if (isEmpty())
return -1;
return data[front];
}
int Rear() {
if (isEmpty())
return -1;
return data[rear];
}
bool isEmpty() {
return (front == rear && front == -1);
}
bool isFull() {
return ((rear + 1) % len == front);
}
};
作者:Roycec
链接:https://leetcode-cn.com/problems/design-circular-queue/solution/cdong-tai-shu-zu-shi-xian-by-roycec-g3qn/
来源:力扣(LeetCode)
3.2 该题的设计思路及伪代码

浙公网安备 33010602011771号