循环队列的两种实现方法
顺序存储结构
示意图参考严蔚敏版《数据结构》。
顺序存储为何宜选循环队列?
队列的顺序表存储中,除了数据域
d
a
t
a
data
data,还应附设两个坐标
f
r
o
n
t
front
front和
r
e
a
r
rear
rear用来记录头结点和尾结点的位置。对于
p
o
p
pop
pop操作,依靠
f
r
o
n
t
+
1
front+1
front+1 这样的上移操作来进行。假设队列中已经有一些元素,经过几次上移后的队列大致如下图所示。
如图,此时队列已满,画斜线的部分表示被 p o p pop pop 的元素(这些元素虽然被弹出,但由于是顺序表存储,其实际的内存还在)。这时如果想要 p u s h push push新的元素,就应该扩大内存空间——那些被抛弃的元素所占的内存就这样被浪费掉了…这显然不是我们想要的。
是否能循环利用?
当然,之前学习过的循环链表可以作为参考对象。使用顺序存储结构的话,可以利用求余这一重要思想来完成循环(之前做的算法题涉及到循环的操作有好多都是利用求余)。当一个元素被
p
o
p
pop
pop后,其所在位置的空间并没有被释放,而是被“假设”不存在了——这只体现在
f
r
o
n
t
front
front标记后移;在空间允许的情况下,新
p
u
s
h
push
push的元素会覆盖掉之前被
p
o
p
pop
pop的元素,一直如是。
这样的话我们一定要知道一个确定的
M
A
X
_
S
I
Z
E
MAX\_SIZE
MAX_SIZE。
初始时,
f
r
o
n
t
=
r
e
a
r
=
0
front=rear=0
front=rear=0,而循环队列下一个则可以用如下公式表示:
(
r
e
a
r
+
1
)
%
M
A
X
_
S
I
Z
E
(rear+1)\%MAX\_SIZE
(rear+1)%MAX_SIZE
同样的,在进行
p
u
s
h
push
push和
p
o
p
pop
pop操作时应该分别进行判满和判空处理。
代码
#include<iostream>
#include<cstdlib>
#define MAX_SIZE 100
#define OK 1
#define ERROR -1
using namespace std;
typedef int ElemType;
typedef int Status;
typedef struct {
ElemType *data;
int front, rear;
}SqQueue;
Status QueueInit(SqQueue &sq)
{
sq.data = (ElemType *)malloc(sizeof(ElemType));
if (!sq.data)
return ERROR;
sq.front = sq.rear = 0;
return OK;
}
int QueueLength(SqQueue sq)
{
return (sq.rear - sq.front + MAX_SIZE) % MAX_SIZE;
}
Status Push(SqQueue &sq, ElemType e)
{
if ((sq.rear + 1) % MAX_SIZE == sq.front) return ERROR;
sq.data[sq.rear] = e;
sq.rear = (sq.rear + 1) % MAX_SIZE;
return OK;
}
Status Pop(SqQueue &sq, ElemType &e)
{
if (sq.rear == sq.front)
return ERROR;
e = sq.data[sq.front];
sq.front = (sq.front + 1) % MAX_SIZE;
return OK;
}
int main()
{
SqQueue sq;
QueueInit(sq);
for (int i = 1;i <= 9;i++)
Push(sq, i);
for (int i = 1;i <= 4;i++)
{
ElemType temp;
Pop(sq, temp);
cout << temp << ' ';
}
return 0;
}
链式存储结构
代码
#include<iostream>
#include<cstdlib>
#define OK 1
#define ERROR -1
using namespace std;
typedef int ElemType;
typedef int Status;
typedef struct node {
ElemType data;
struct node *next;
}Lnode;
Status InitQueue(Lnode *rear)
{
//rear = (Lnode *)malloc(sizeof(Lnode));
if (!rear)
return ERROR;
rear->next = rear;
return OK;
}
Status EnQueue(Lnode **rear, ElemType e)
{
Lnode *temp = (Lnode *)malloc(sizeof(Lnode));
if (!temp)
return ERROR;
temp->data = e;
temp->next = (*rear)->next;
(*rear)->next = temp;
(*rear) = temp;
return OK;
}
Status visit(Lnode *rear)
{
Lnode *temp = rear->next;
while (temp != rear) // 存疑2,为何不输出
{
cout << temp->next->data << ' ';
temp = temp->next;
}
return OK;
}
int main()
{
Lnode *rear;
rear = (Lnode *)malloc(sizeof(Lnode));
InitQueue(rear);
for (int i = 1;i <= 9;i++)
{
EnQueue(&rear, i);
//cout << rear->data << ' ';
}
//cout << endl << rear->data;
visit(rear);
system("pause");
return 0;
}