队列的c语言实现

#include <stdio.h>
#include <stdlib.h>
//实现队列的数据结构
//队列是只允许队尾插入,队头删除的存储结构

//先来看顺序存储结构(数组实现)
#define OK 1
#define ERROR -1
#define MAX 10 //定义队列的长度
typedef int ElemType;
typedef int Status;
typedef struct {
    ElemType data[MAX];
    int head;//队头
    int tail;//队尾
}Queue;

//初始化操作
Status InitQueue(Queue *Q){
   // memset(Q->data,'\0',sizeof(ElemType)*MAX);
    Q->head=0;
    Q->tail=0;//指向队尾元素的下一个位置
    return OK;
}
//产生测试队列
Status CreateQueue(Queue *Q,int n){
    //初始化队列

//产生一个长度为n的测试队列
    srand(time(0));
    int i;
    for(i=0;i<n;i++){
        Q->data[(Q->tail)++]=rand()%100+1;
    }
    return OK;

}

//入队操作
Status EnQueue(Queue *Q,ElemType e){
    //判断是否队满
    if(Q->tail==MAX){
        printf("队列已满,不能入队");
        return ERROR;
    }

    Q->data[Q->tail]=e;
     ++(Q->tail);
    return OK;
}
//出队操作
Status DeQueue(Queue *Q,ElemType *e){
    //将出队的元素传给e
    //判读是否为空队
    if(Q->tail==0 || Q->tail<=Q->head){
        printf("空队列,无法出队!");
        return ERROR;
    }
    *e=Q->data[Q->head];
    //队头后移
    ++(Q->head);
    return OK;

}

int main()
{
    Queue Q;
    int i,n,e;
    if(OK!=InitQueue(&Q)){
        printf("初始化失败!");
        return ERROR;
    }
    printf("输入要产生的队列长度!");
    scanf("%d",&n);
    if(n>MAX){
        printf("已超出队列的最大长度");
        return ERROR;
    }
    if(OK==CreateQueue(&Q,n)){
        //输出队列的值
        for(i=Q.head;i<Q.tail;i++){
            printf("%d\t",Q.data[i]);
        }
        printf("\n头为%d\n",Q.head);
        printf("尾为%d\n",Q.tail);
    }
    printf("输入要插入的元素!\n");
    while(1==scanf("%d",&e)){
        if(OK==EnQueue(&Q,e)){
            for(i=Q.head;i<Q.tail;i++){
            printf("%d\t",Q.data[i]);
        }
        printf("\n头为%d\n",Q.head);
        printf("尾为%d\n",Q.tail);
        }else{
            break;
        }
    }
    printf("元素依次出队\n");
    while(OK==DeQueue(&Q,&e)){
        printf("出队元素为%d\t,队头为%d\n",e,Q.head);
    }
    return 0;
}

以上代码是队列的简单实现;由于出队时仅仅是将队头后移,入队时队尾只能往后移动;会出现队头挨近队尾时,队头前面大量空间未被使用的情况,从而浪费了大量的存储空间。

考虑入队时,队尾如果到达存储队列的数组的末尾时,而实际上队列并没有满,前面还有空余的存储空间;队尾则移到数组的首部;执行后续操作。


循环队列是首尾相接的循序存储结构。


循环队列的数据结构和简单队列的结构一样;只是入队、出队、求长等需要变化一下。

Status EnQueue2(Queue *Q,ElemType e){
    //循环队列同样要判断队列是否为空;
    //注意循环队列的head可能大于tail

    //循环队列满的条件判断
     if((Q->tail+1)%MAX==Q->head){
        //队列满了
        printf("队列已满!\n");
        return ERROR;
     }
     Q->data[Q->tail]=e;
     //Q->tail的范围在0~MAX-1;
     Q->tail=(Q->tail+1)%MAX;
     return OK;

}

Status DeQueue2(Queue *Q,ElemType *e){
// 循环队列的出队操作
    //判断队列是否为空
    //此处会有一个bug;当输入的队长度为MAX时,初始化后的Q->tail=MAX;而Q->head的范围是0~MAX-1;永远无法满足条件Q->head==Q->tail
    if(Q->head==Q->tail){
        printf("循环队列为空!");
        return ERROR;
    }

    *e=Q->data[Q->head];
    Q->head=(Q->head+1)%MAX;
    return OK;

}

int QLen(Queue Q){
    return (Q.tail-Q.head+MAX)%MAX;
}


同线性表一样,队列既然有循序存储结构,就有链式存储结构;队列的链式存储结构主要是为了解决队列存储空间的问题。


#include <stdio.h>
#include <stdlib.h>
//队列的链式存储,链式存储的共性是不必考虑存储空间的溢出

//队列的链式存储的基本数据结构其实就是链表;我们还是用单链表来实现
#define OK 1
#define ERROR -1
typedef int Status;
typedef int ElemType;
typedef struct {
    ElemType data;
    struct Node *next;
}Node,*QNode;

//利用单链表的基本数据结构来定义队列的数据结构

typedef struct{
    //队列有结点;头指针和尾指针
    QNode head,tail;//QNode是指向结点的指针,该类型已经包含结点,不需要再定义结点了
    //head这里设置为指向队头的结点,不是队头,是指向队头的结点
}QList;
//队列初始化
Status InitQ(QList *Q){
    //创建一个临时结点
    QNode N;
    N=(QNode)malloc(sizeof(Node));
    N->data=1;
    N->next=NULL;
    //让队列的首尾指针都指向他
    Q->head=N;
    Q->tail=N;
    return OK;
}

//入队操作
Status EnQue(QList *Q,ElemType e){
//将元素e入队;
    QNode N;
    N=(QNode)malloc(sizeof(Node));
    //需要考虑存储是否溢出
    if(!N){
        printf("存储分配失败!\n");
        return ERROR;
    }
    N->data=e;
    N->next=NULL;
    Q->tail->next=N;
    Q->tail=N;
    return OK;
}
//出队操作
Status DeQue(QList *Q,ElemType *e){
    //判断是否为空
    if(Q->head==Q->tail){
        printf("队列为空");
        return ERROR;
    }
    //注意这里设置的队头是Q->head->next指向的结点;Q->head作为链表的头结点

    QNode T;
    T=Q->head->next;//将头结点传给临时结点

    *e=T->data;
    Q->head->next=T->next;
    //如果队头到达队尾时(临时结点是尾结点),出队后,队尾指针要指向头结点
    if(T==Q->tail){
        Q->tail=Q->head;
    }
    //释放队头结点占的内存;一般的删除操作都要新建一个临时结点,接收要删除的结点,然后调整指针,释放内存
    free(T);
    return OK;
}



int main()
{
    QList Q;


    if(OK==InitQ(&Q)){
        printf("初始化成功!\n");
    }
    int e;
    e=1;

    EnQue(&Q,5);

     QNode t;
     t=Q.head->next;
printf("%d\n",t->data);
     EnQue(&Q,6);
     t=t->next;
printf("%d\n",t->data);
DeQue(&Q,&e);
printf("%d\n",e);
DeQue(&Q,&e);
printf("%d\n",e);
DeQue(&Q,&e);
printf("%d\n",e);
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值