数据结构之队列

队列:是只允许在一端进行插入操作,另一端进行删除操作的线性表.
先进先出,有队头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;
 } 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值