队列
特点:
1.先进先出
2.对队列的操作可以理解为头删+尾插
在这里我们主要实现循环队列
循环队列的结构设计
typedef struct Que
{
Elemtype *data; //存储空间
int front;
int rear;
}SeQueue;
其他参数
#define MAXQSIZE 10
typedef int Elemtype;
初始化
void InitQue(SeQueue *que)
{
assert(que != NULL);
if(que == NULL)
{
printf("InitQue : : 空间申请失败!\n");
exit(0);
}
que->data = (Elemtype*)malloc(sizeof(Elemtype) * MAXQSIZE);
assert(que->data != NULL);
que->front = que->rear = 0;
}
判空
队列为空时,front和rear的值相等,但不一定为0
int IsEmpty(SeQueue *que)
{
assert(que != NULL && que->data != NULL);
if(que->rear == que->front)
return 1;
else
return 0;
}
判满
对于循环队列来说,当队尾指针处再加入一个元素后,刚好回到队头指针的位置时,这时会损失一个存储空间,但这种逻辑简单,证明该队列已满,因此对于循环队列来说:
判满条件为:
(rear + 1) % MAXSIZE == front
int IsFUll(SeQueue *que)
{
assert(que != NULL && que->data != NULL);
if((que->rear+1) % MAXQSIZE == que->front)
return 1;
else
return 0;
}
入队
void Push(SeQueue *que,Elemtype val)
{
assert(que != NULL && que->data != NULL);
if(IsFUll(que))
return;
else
{
que->data[que->rear] = val;
que->rear = (que->rear+1) % MAXQSIZE;
}
}
出队
bool Pop(SeQueue *que,Elemtype *rtval)
{
assert(que != NULL && que->data != NULL);
if(IsEmpty(que))
return false;
else
{
*rtval = que->data[que->front];
que->front = (que->front+1) % MAXQSIZE;
return true;
}
}
遍历队列
void Show(SeQueue *que)
{
int i = que->front;
printf("队列中的元素为:");
while((i % MAXQSIZE) != que->rear)
{
printf("%d",que->data[i]);
i++;
}
printf("\n");
}
两个队列实现一个栈
初始化
void InitQueStack(QueStack *st)
{
assert(st != NULL);
if(st == NULL)
{
printf("InitQueStack::Error!\n");
exit(0);
}
InitQue(&st->q1);
InitQue(&st->q2);
}
判满
int IsFullQueStack(QueStack *st)
{
if(IsFUll(&st->q1) && IsFUll(&st->q2))
return 1;
else
return 0;
}
判空
int IsEmptyQueStack(QueStack *st)
{
if(IsEmpty(&st->q1) && IsFUll(&st->q2))
return 1;
else
return 0;
}
入栈
int PushQueStack(QueStack *st,Elemtype val)
{
assert(st != NULL);
if(st == NULL)
{
printf("PushQueStack::Error!\n");
exit(0);
}
//队列1不为空
if(!IsEmpty(&st->q1))
{
Push(&st->q1,val);
}
//队列2不为空或者两个队列都为空时
else
{
Push(&st->q2,val);
}
}
出栈
int PopQueStack(QueStack *st)
{
assert(st != NULL);
if(st == NULL)
{
printf("PopQueStack::Error!\n");
exit(0);
}
if(IsEmpty(&st->q1) && IsEmpty(&st->q2))
{
return 0;
}
SeQueue *from = NULL;//用于记录有元素队列的首地址
SeQueue *to = NULL;
//看哪个队列里面有元素存在
if(!IsEmpty(&st->q1))
{
from = &st->q1;
to = &st->q2;
}
else
{
to = &st->q1;
from = &st->q2;
}
Elemtype x;
//有元素的队列from中不只一个元素,因此需要先对这个队列进行出队列操作,保证只剩下一个元素再出栈
while(from->size>1)
{
Elemtype tmp = Top(from);
Pop(from,&x);
Push(to,tmp);
}
Pop(from,&x);
}
C++
思路:q1指针指向存储新入栈的元素,q2指针指向存放已经调整好的栈的数据,反复调整交换指针。
class MyStack {
public:
MyStack() {
q1 = new queue<int>;
q2 = new queue<int>;
}
~MyStack() {
delete q1;
delete q2;
q1 = nullptr;
q2 = nullptr;
}
void push(int x) {
q1->push(x);
while(!q2->empty())
{
q1->push(q2->front());
q2->pop();
}
queue<int> *tmp = q1;
q1 = q2;
q2 = tmp;//此时q1仍然指向需要新入队元素的那个队列
}
int pop() {
int val = q2->front();
q2->pop();
return val;
}
int top() {
return q2->front();
}
bool empty() {
return q2->empty();
}
private:
queue<int> * q1;//始终存储新入队的元素
queue<int> * q2;//始终存储调整好的元素
};