队列:是只允许在一端进行插入操作,另一端进行删除操作的线性表.
先进先出,有队头front和队尾rear。
一、循环队列:首尾相接的队列成为循环队列。
循环队列为空的条件:Q.front==Q.real
循环队列为满的条件: (Q->rear+1)%MAXSIZE == Q->front
循环队列的长度: (Q.real-Q.front+MAXSIZE)%MAXSIZE
#include "stdio.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */
//队列:先进新出原则,有两个指针,一个front(头指针),另一个为real(尾指针)
//在这里,我们以循环队列为主要
//循环队列:首尾相接 的顺序存储结构
//循环队列有什么用?
//因为队列只能从一边进,另一边出, 而队列的入队和出队的时间复杂度为O(1),
//这样会造成很多位置的空缺 ,所以循环队列就是为了节省空间
//一个队列MAXSIZE,那么最多只能存放MAXSIZE-1个数则满
//队列为空的条件:Q.front==Q.real
//队列为满的条件: (Q->rear+1)%MAXSIZE == Q->front
//队列的长度: (Q.real-Q.front+MAXSIZE)%MAXSIZE
typedef int Status;
typedef int Ele;
//定义结构
typedef struct {
Ele data[MAXSIZE];
int front; //头指针
int real; //尾指针 若队列不空,指向队列尾元素的下一个位置
}Queue;
//初始化,一个空队列
Status InitQueue(Queue *Q){
Q->front = 0;
Q->real = 0;
return OK;
}
//清空队列
Status ClearQueue(Queue *Q){
Q->front = Q->real =0;
return OK;
}
//判断是否为空
Status QueueEmpty(Queue Q){
if(Q.front==Q.real){
printf("队列为空\n");
return TRUE;
}else{
printf("队列不为空\n");
return FALSE;
}
}
//返回Q的个数,也就是队列的长度
int QueueLength(Queue Q){
return (Q.real-Q.front+MAXSIZE)%MAXSIZE;
}
//入队
Status InQueue(Queue *Q,Ele e){
if((Q->real+1)%MAXSIZE == Q->front){ //队满判断
return ERROR;
}
Q->data[Q->real] = e; //将新元素赋给队尾
Q->real = (Q->real+1)%MAXSIZE; //再将队尾指针指向新增元素的下一个位置
return OK;
}
//出队
Status OutQueue(Queue *Q,Ele e){
if(Q->front==Q->real){ /* 队列空的判断 */
return ERROR;
}
e = Q->data[Q->front]; //出队的元素
printf("%d ",e);
Q->front = (Q->front+1)%MAXSIZE; //头指针向后移动一个位置
return OK;
}
//遍历
Status QueueVisit(Queue Q){
int i;
printf("该队列的元素为:\n");
i = Q.front;
while(i!=Q.real){ //是否到达队尾的判断
printf("%d ",Q.data[i]);
i = (i+1)%MAXSIZE;
}
printf("\n");
return OK;
}
int main(){
int j;
Queue Q;
Ele e;
printf("队列初始化之后\n");
InitQueue(&Q);
QueueEmpty(Q);
//入队
//一个队列MAXSIZE=20,那么最多只能存放19个数则满
printf("入队后:\n");
for(j=1;j<=MAXSIZE;j++){
InQueue(&Q,j);
}
QueueVisit(Q);
printf("队列的长度=%d\n",QueueLength(Q));
//出队
printf("出队后:\n");
for(j=1;j<=5;j++){
OutQueue(&Q,e);
}
QueueEmpty(Q);
QueueVisit(Q);
printf("队列的长度=%d",QueueLength(Q));
return 0;
}
二、链队列:队列的链式存储结构,在操作上与链表的操作基本一致。
入队图:
出队图:
#include "stdio.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
//链队列:由于循环队列的存储被确定在一定的范围内,故采用链队列来完善这样的不足
//这也是一种链式存储结构
//定义
typedef int Status;
typedef int QEle;
typedef struct QNode{ //结点
QEle data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct { //队列结构
QueuePtr front,rear;
}LinkQueue;
//初始化
Status InitQueue(LinkQueue *Q){
Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
if(!Q->front){
return ERROR;
}
Q->front->next = NULL;
return OK;
}
//队列清空
Status ClearQueue(LinkQueue *Q){
QueuePtr p,q;
Q->rear = Q->front;
p = Q->front->next; //此时的Q->front->next为第一个结点
Q->front->next = NULL; //再把原来的赋值为空
while(p){
q = p;
p = p->next;
free(q);
}
return OK;
}
//销毁队列Q ,销毁之后队列也就没了
Status DestroyQueue(LinkQueue *Q){
while(Q->front){
Q->rear = Q->front->next;
free(Q->front);
Q->front = Q->rear;
}
return OK;
}
//是否为空
int IsEmpty(LinkQueue Q){
int i = 0;
if(Q.front == Q.rear){
printf("该队列为空\n");
return TRUE;
}else{
printf("该队列不为空\n");
return FALSE;
}
}
//队列的长度
int QueueLength(LinkQueue *Q){
int i=0;
QueuePtr p;
p = Q->front;
while(p!=Q->rear){
i++;
p = p->next;
}
return i;
}
//入队操作
Status InQueue(LinkQueue *Q,QEle e){
QueuePtr s = (QueuePtr)malloc(sizeof(QNode));
if(!s){
return ERROR;
}
s->data = e;
s->next = NULL;
Q->rear->next = s; //将原来的末尾的元素的后继赋给新结点s
Q->rear = s; //将末尾的指针指向s
return OK;
}
//出队操作
Status OutQueue(LinkQueue *Q,QEle e){
QueuePtr p;
if(Q->front == Q->rear){
return ERROR;
}
p = Q->front->next; //将欲删除的队头结点赋给p
e = p->data;
printf("出队的元素为:%d ",e);
Q->front->next = p->next; // 将原队头结点的后继p->next赋值给头结点后继
if(Q->rear == p){ // 若队头就是队尾,则删除后将rear指向头结点
Q->rear = Q->front;
}
free(p);
printf("\n");
return OK;
}
//遍历操作
Status LinkQueueVisit(LinkQueue *Q){
QueuePtr p;
p = Q->front->next;
printf("该队列的元素为:\n");
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return OK;
}
int main(){
int i ;
QEle e;
LinkQueue Q;
//初始化
printf("初始化\n");
InitQueue(&Q);
IsEmpty(Q);
LinkQueueVisit(&Q);
//入队
printf("入队后\n");
for(i=0;i<10;i++){
InQueue(&Q,i);
}
LinkQueueVisit(&Q);
//出队
printf("出队后\n");
for(i=0;i<3;i++){
OutQueue(&Q,e);
}
LinkQueueVisit(&Q);
printf("队列长度=%d\n",QueueLength(&Q));
//清空队列
ClearQueue(&Q);
printf("清空队列Q->front=%d,Q->rear=%d\n",Q.front,Q.rear);
//销毁队列
DestroyQueue(&Q);
printf("销毁队列Q->front=%d,Q->rear=%d",Q.front,Q.rear);
return 0;
}