1、队列的定义
队列:(Queue)先进先出,后进后出,一端进行插入另一端进行删除。顺序队列就是循环队列,下面会说:
2、难点一
与栈相比而言,栈的入栈和出栈都是在栈顶进行操作,时间复杂度都为O(1),但是如何让队列的插入和删除的(入队和出队)时间复杂度为O(1)?
将队列想象为循环的,实际是不存在的,然后对其进行类似于魔方阵操作,即取模操作,来进行判满操作。
3、难点二
判空和判满条件都为:队头指针==队尾指针,如何让解决
解决方案1:再添加一个条件,即:判断有效节点个数,队头=队尾&&有效节点个数不为0,如下图所示:
**解决方案2:浪费最后一个空间,让其进行标记,当队尾向前跑一步之后,队头=队尾,如下:(队尾+1)%MAXSIZE=队头;**也有可能不在0相遇,下面只是举例。
4、难点三
两种情况:
有效节点个数=(队尾-队头+MAXSIZE)%MAXSIZE
前面的+MAXSIZE作用是为了防止队尾-队头结果出现负数,后面的%MAXSIZE是为了防止加多了。
5、结构体设计
typedef int ELEM_TYPE;
typedef struct Queue
{
ELEM_TYPE* base;//用来保存malloc来的数组首地址
int front;//保存队头下标
int tail;//保存队尾下标
//int length;用此来保存有效节点个数,更加方便
/*用指针也可以,只不过用整型更方便一点*/
}queue,*Pqueue;
6、头文件
typedef int ELEM_TYPE;
typedef struct Queue
{
ELEM_TYPE* base;//用来保存malloc来的数组首地址
int front;//保存队头下标
int tail;//保存队尾下标
//int length;用此来保存有效节点个数,更加方便
/*用指针也可以,只不过用整型更方便一点*/
}queue,*Pqueue;
//初始化
void Init_Queue(Pqueue pq);
//入队
bool push(Pqueue pq, ELEM_TYPE val);
//出队(如果出队的话,需要返回一下出队的值,因此要多加一个参数来保存,在主函数中可以来保存,下同)
bool Pop(Pqueue pq,ELEM_TYPE *rtval);
//获取队头元素值
bool Get_Top(Pqueue pq, ELEM_TYPE* rtval);
//获取队尾元素
bool Get_Tail(Pqueue pq, ELEM_TYPE* rtval);
//获取有效元素个数
int Get_length(Pqueue pq);
//判空
bool Is_Empty(Pqueue pq);
//判满
bool Is_Full(Pqueue pq);
//清空
void Clear(Pqueue pq);
//销毁
void Destory(Pqueue pq);
//打印
void Print(Pqueue pq);
7、函数实现
#if 1
#include"Queue.h"
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define MAXSIZE 100
//初始化
void Init_Queue(Pqueue pq)
{
assert(pq != NULL);
pq->base = (ELEM_TYPE*)malloc(sizeof(ELEM_TYPE) * MAXSIZE);
assert(pq->base != NULL);
pq->front = pq->tail = 0;//让头尾都指向0下标
}
//入队(队尾入队)
bool push(Pqueue pq, ELEM_TYPE val)
{
assert(pq != NULL);
if (Is_Full(pq))
{
return false;
}
pq->base[pq->tail] = val;
pq->tail = (pq->tail + 1) % MAXSIZE;//目的是将最后一个空间保留下来,防止越界,同时做到最后一个空间被浪费
return true;
}
//出队(如果出队的话,需要返回一下出队的值,因此要多加一个参数来保存,在主函数中可以来保存,下同)
bool Pop(Pqueue pq, ELEM_TYPE* rtval)
{
assert(pq != NULL);
if (Is_Empty(pq))
{
return false;
}
*rtval = pq->base[pq->front];
pq->front = (pq->front + 1) % MAXSIZE;//同上防止越界
return true;
}
//获取队头元素值
bool Get_Top(Pqueue pq, ELEM_TYPE* rtval)
{
assert(pq != NULL);
if (Is_Empty(pq))
{
return false;
}
*rtval = pq->base[pq->front];
return true;
}
//获取队尾元素
bool Get_Tail(Pqueue pq, ELEM_TYPE* rtval)
{
assert(pq != NULL);
if (Is_Empty(pq))
{
return false;
}
*rtval = pq->base[pq->tail];
return true;
}
//获取有效元素个数
int Get_length(Pqueue pq)
{
assert(pq != NULL);
return ((pq->tail - pq->front + MAXSIZE) % MAXSIZE);
}
//判空
bool Is_Empty(Pqueue pq)
{
assert(pq != NULL);
if (pq->front == pq->tail)
{
return true;
}
return false;
}
//判满
bool Is_Full(Pqueue pq)
{
assert(pq != NULL);
if ((pq->tail+ 1) % MAXSIZE == pq->front)
{
return true;
}
return false;
}
//清空
void Clear(Pqueue pq)
{
assert(pq != NULL);
pq->front = pq->front = 0;
}
//销毁
void Destory(Pqueue pq)
{
assert(pq != NULL);
Clear(pq);
free(pq);
pq = NULL;
}
//打印
void Print(Pqueue pq)
{
assert(pq != NULL);
for (int i = pq->front; i != pq->tail; i=(i+1)%MAXSIZE)
{
printf("%d ", pq->base[i]);
}
printf("\n");
}
int main()
{
struct Queue x = {};
Pqueue pq = &x;
Init_Queue(pq);
for (int i = 0; i < 99; i++)//最后一个位置不能放数据
{
push(pq, i);
}
Print(pq);
printf("队列是否已满%d ", Is_Full(pq));
int rtval;
for (int i = 0; i < 99; i++)//最后一个位置不能放数据
{
Pop(pq, &rtval);
printf("%d ", rtval);
}
}
#endif
运行结果: