数据结构之队列(循环队列)

循环队列的代码演示

由于队列的出队操作是head++,直接向后移动,当队尾达到队列设定的长度时,会出现假溢出的现象(即可能head前面还可以插入),因此可以改为循环队列,而循环队列可能出现真溢出的现象,因此需要扩容操作。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

typedef struct Queue{
    int *data;
    //队首,和队尾,队列的长度
    int head,tail,length;
    //循环队列记录节点个数的变量
    int cnt;
}Queue;
//队列的初始化
Queue *init(int n){
    Queue *q=(Queue *)malloc(sizeof(Queue));
    q->data=(int *)malloc(sizeof(int)*n);
    q->length=n;
    q->head=0;
    q->cnt=0;
    q->tail=0;
    return q;
}
//释放内存
void clear(Queue* q){
    if(q==NULL) return ;
    free(q->data);
    free(q);
    return ;
}
//队首元素
int front(Queue *q){
    return q->data[q->head];
}
//判断队列是否为空
int empty(Queue *q){
    return q->cnt==0;
}
//循环队列的扩容操作
int expand(Queue *q){
    int extr_size=q->length;
    //新开辟数组空间p,记录新队列的元素
    int *p;
    //判断是否有空间可以扩容,每次除以2,
    while(extr_size){
        p=(int *)malloc(sizeof(q->length+extr_size));
        //如果p不为空,说明开辟地址成功,直接break;
        if(p) break;
        extr_size>>=1;
    }
    if(p==NULL) return 0; //开辟不了多余的空间,直接返回
    //把数据拷贝到新的地址空间中
    for(int i=q->head,j=0;j<q->cnt;j++){
        p[j]=q->data[(i+j)%q->length];
    }
    //释放原来的地址空间
    free(q->data);
    //更新数据域
    q->data=p;
    //更新长度
    q->length+=extr_size;
    //更新队首和队尾的下标
    q->head=0;
    q->tail=q->cnt;
    return 1;
}

//入队操作
int push(Queue *q,int val){
    if(q==NULL) return 0;
    if(q->cnt==q->length){
        if(!expand(q)) return 0;
        printf("expand success!Queue->size = %d\n",q->length);
    }
    q->data[q->tail++]=val;
    //如果队尾到达上限,更新下标值
    if(q->tail==q->length) q->tail=0;
    q->cnt+=1;
    return 1;
}
//出队操作
int pop(Queue *q){
    if(q==NULL) return 0;
    if(empty(q)) return 0;
    q->head++;
    //如果队首达到上限,更新下标值。
    if(q->head==q->length) q->head=0;
    q->cnt-=1;
    return 1;
}

void output(Queue *q){
    printf("Queue: [");
    for(int i=q->head,j=0;j<q->cnt;i++,j++){
        j && printf(", ");
        printf("%d",q->data[i%q->length]);
    }
    printf("]\n");
    return;
}

int main(){
    srand(time(0));
    #define max_op 20
    Queue *q =init(max_op);
    //模拟扩容操作
    for(int i=0;i<max_op*2;i++){
        int val=rand()%100;
        int op=rand()%4;
        switch(op){
            case 0:
            case 1:
            case 2:{
                printf("push %d to the Queue! status = %d\n",val, push(q,val));
            }break;
            case 3:{
                printf("pop %d ",front(q));
                printf(" from the Queue! status = %d\n",pop(q));
            }break;
        }
        output(q);
        printf("\n");
    }
    #undef max_op
    clear(q);
    return 0;
}

pop 0  from the Queue! status = 0
Queue: []

push 87 to the Queue! status = 1
Queue: [87]

push 41 to the Queue! status = 1
Queue: [87, 41]

push 69 to the Queue! status = 1
Queue: [87, 41, 69]

push 42 to the Queue! status = 1
Queue: [87, 41, 69, 42]

push 69 to the Queue! status = 1
Queue: [87, 41, 69, 42, 69]

push 81 to the Queue! status = 1
Queue: [87, 41, 69, 42, 69, 81]

push 77 to the Queue! status = 1
Queue: [87, 41, 69, 42, 69, 81, 77]

pop 87  from the Queue! status = 1
Queue: [41, 69, 42, 69, 81, 77]

push 6 to the Queue! status = 1
Queue: [41, 69, 42, 69, 81, 77, 6]

push 45 to the Queue! status = 1
Queue: [41, 69, 42, 69, 81, 77, 6, 45]

pop 41  from the Queue! status = 1
Queue: [69, 42, 69, 81, 77, 6, 45]

push 75 to the Queue! status = 1
Queue: [69, 42, 69, 81, 77, 6, 45, 75]

pop 69  from the Queue! status = 1
Queue: [42, 69, 81, 77, 6, 45, 75]

push 5 to the Queue! status = 1
Queue: [42, 69, 81, 77, 6, 45, 75, 5]

pop 42  from the Queue! status = 1
Queue: [69, 81, 77, 6, 45, 75, 5]

push 68 to the Queue! status = 1
Queue: [69, 81, 77, 6, 45, 75, 5, 68]

push 0 to the Queue! status = 1
Queue: [69, 81, 77, 6, 45, 75, 5, 68, 0]

push 19 to the Queue! status = 1
Queue: [69, 81, 77, 6, 45, 75, 5, 68, 0, 19]

push 58 to the Queue! status = 1
Queue: [69, 81, 77, 6, 45, 75, 5, 68, 0, 19, 58]

pop 69  from the Queue! status = 1
Queue: [81, 77, 6, 45, 75, 5, 68, 0, 19, 58]

pop 81  from the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58]

push 32 to the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58, 32]

push 72 to the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58, 32, 72]

push 39 to the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39]

push 42 to the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42]

push 62 to the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62]

push 24 to the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24]

push 1 to the Queue! status = 1
Queue: [77, 6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1]

pop 77  from the Queue! status = 1
Queue: [6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1]

push 62 to the Queue! status = 1
Queue: [6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62]

push 70 to the Queue! status = 1
Queue: [6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70]

push 26 to the Queue! status = 1
Queue: [6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26]

push 43 to the Queue! status = 1
Queue: [6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26, 43]

push 91 to the Queue! status = 1
Queue: [6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26, 43, 91]

expand success!Queue->size = 40
push 12 to the Queue! status = 1
Queue: [6, 45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26, 43, 91, 12]

pop 6  from the Queue! status = 1
Queue: [45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26, 43, 91, 12]

push 85 to the Queue! status = 1
Queue: [45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26, 43, 91, 12, 85]

push 83 to the Queue! status = 1
Queue: [45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26, 43, 91, 12, 85, 83]

push 27 to the Queue! status = 1
Queue: [45, 75, 5, 68, 0, 19, 58, 32, 72, 39, 42, 62, 24, 1, 62, 70, 26, 43, 91, 12, 85, 83, 27]


上一篇:555555555555555555555


下一篇:iOS小技巧 - 为按钮设置不同状态下的背景色