数据结构队列 2021/8/6 17:40
顺序实现队列
#include<iostream>
using namespace std;
#define MaxSize 10
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];
int front, rear;
}SqQuene;
/*
* 队列的初始化
*/
void InitQuene(SqQuene &Q)
{
Q.rear = Q.front = 0;
}
/*
* 判断队列是否为空
*/
bool QueneEmpty(SqQuene Q)
{
if (Q.front == Q.rear)
return true;
else
return false;
}
/*
* 入队,取余操作让该队列在逻辑上是循环的,称为循环队列
*/
bool EnQuene(SqQuene& Q, ElemType e)
{
if ((Q.rear+1)%MaxSize==Q.front)//若队尾的下一位是队头,则说明队列已满
return false;
Q.data[Q.rear] = e;
Q.rear=(Q.rear+1)%MaxSize;
return true;
}
/*
* 出队
*/
bool DeQuene(SqQuene& Q, ElemType e)
{
if (Q.rear == Q.front)//队空则不存在出队
return false;
e = Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;
return true;
}
/*
* 获取队头元素
*/
bool GetHead(SqQuene Q, ElemType e)
{
if (Q.front == Q.rear)
return false;
e = Q.data[Q.front];
return true;
}
//判断队满和队空:1.当rear和front指向同一位置为空,rear下一位是front为满,这种方法会浪费一位储存空间
//2.在队列中定义size储存当前队列的长度,此时rear和front指向同一位置时有队满和队空两种情况
//3.在队列中定义一个tag变量表示最近的一次成功操作是插入和删除,这种情况下,当rear和front指向同一位置时,只要判断最近的一次操作是什么就可以确定当前是队满还是队空
//其他出题方法:王道介绍的都是队尾指针指向队列末尾元素的下一位的情况,题中可能会出现队尾指针指向队尾元素的情况,
//此时要注意审题,注意修改入队出队操作(先移再入还是先入再移),还要修改初始化的方式,
//让rear指向-1(这样移入一个元素后才能指向这个元素所在的位置)
//同时此时判断队空和队满的条件也币一样,当队满时,rear和front指向的不再是同一个位置,
//此时我们要么牺牲一个位置的空间,要么在队列中定义一个表示队列长度的变量
1.初始化:将队尾和队首都指向0
2.判空:查看队首和队尾指针是否指向相同,相同则为空
3.入队:队尾指针的取余操作让队列在逻辑上是循环的,成为循环队列。具体操作为:首先判满,不满则在队尾插入新元素,将队尾指针加一
4.出队:判空,输出队首指针指向的值,然后将队首指针加一
5.获取队首元素:判空,不空则取出队首指针指向的元素
6.注意上面代码注释中提到的各种考察的特殊情况!!!!!!!!!
链式队列
链式队列-不带头结点
#include<iostream>
#define MaxSize 10
using namespace std;
typedef int ElemType;
typedef struct LinkNode {
ElemType data;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode* front, * rear;
}LinkQuene;
/*
* 队列的初始化
*/
bool InitQuene(LinkQuene& Q)
{
Q.front = Q.rear = NULL;
return true;
}
/*
* 队列判空
*/
bool IsEmpty(LinkQuene Q)
{
if (Q.front==NULL)
return true;
else
return false;
}
/*
* 入队
*/
bool EnQuene(LinkQuene& Q,ElemType e)
{
LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode));
p->data = e;
p->next = NULL;
if (Q.front == NULL)//如果是入队的第一个结点
{
Q.front = p;
Q.rear = p;
}
else
{
Q.rear->next = p;
Q.rear = p;
}
return true;
}
1.初始化:不带头结点,则将队尾和队首指针指空
2.判空:队首指针指向NULL则为空
3.入队:由于没有头结点,入队的时候要先判断是否是该队列插入的第一个结点(即队首指针所指是否为空),如果是,则将队首指针和队尾指针均指向该结点;如果不是,则将队尾指针的next指向该结点,再将队尾指针指向该结点
链式队列-带头结点
#include<iostream>
#define MaxSize 10
using namespace std;
typedef int ElemType;
typedef struct LinkNode {
ElemType data;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode* front, * rear;
}LinkQuene;
/*
* 队列的初始化
*/
bool InitQuene(LinkQuene &Q)
{
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));//初始化时队头队尾指针都指向头结点
Q.front->next = NULL;
return true;
}
/*
* 队列判空
*/
bool IsEmpty(LinkQuene& Q)
{
if (Q.rear == Q.front)
return true;
else
return false;
}
/*
* 入队
*/
bool EnQuene(LinkQuene &Q,ElemType e)
{
LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode));
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return true;
}
/*
* 队头元素出队
*/
bool DeQuene(LinkQuene& Q, ElemType e)
{
if (Q.front == NULL)
return false;
LinkNode* p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (p == Q.rear)//如果当前出队的是队尾元素
Q.rear = Q.front;
free(p);
return true;
}
//链式队列不会出现队满的情况
//双端队列:主要考察输出序列的合法性
//栈在表达式求值当中的应用:
//中缀转后缀:机算中遵循左优先的原则(若两个运算符哪个先算都一样,则优先计算左侧的)后缀转中缀:从左向右扫描,栈中弹出操作数的时候,先弹出的是右操作数
//中缀转前缀:右优先 前缀转中缀:从右向左扫描,弹出操作数的时候,先弹出的是左操作数
1.初始化:由于有头结点,因此初始化时将头结点的next指空
2.判空:当队尾指针和队首指针指向的是同一个位置是为空(此时指向的都是头结点)
3.入队:创建一个新的结点,将待入队的值赋给新的结点,然后插入队列(将新的结点的next指空,将队尾指针的next指向新的结点,再将队尾指针指向新结点)
4.队头元素出队:若出队的元素不是队尾元素,则出队后将队首指针的next指向该结点的next;若出队的是队尾元素,则出队后需要将队尾指针指向队首(此时只剩下头结点)
5.注意上面注释中栈的应用的问题!!!!!!!
加油