数据结构队列之环形队列的动态数组实现:queue

来源:互联网 发布:搞笑自拍软件 编辑:程序博客网 时间:2024/05/21 21:35

queue: 也是一种线性的数据结构,其操作一般来讲也是受限的,典型特征是(First in, First out, FIFO)先进先出;

        进入队列的元素总是在队列的tail入队,离开队列的元素总是从队列的head离开。

其实实现有多种方式:

1. 用链表实现,head指针指向queue的head, tail指针指向queue的tail;

                     使用的内存空间就是队列中所有元素节点的空间,但是此实现无法随机访问队列中的元素(这是链表本质决定的)。

                     使用链表的实现会当元素频繁入队的话,会频繁的分配内存空间; 当元素入队时也要频繁地释放元素的内存空间。

2. 用数组实现:

         a. 静态数组的实现:有限容量的队列,一般情况下通过实现环形queue以实现数组空间的充分利用。此实现,使用于具体需求确定的情形。 

         b. 动态数组的实现:动态数组实现的环形queue,除了具有静态数组实现的环形queue的优点外,还能根据需求的变化,自动的调整队列的内存。(可谓有点智能)。 


环形队列的实现要点:可谓是队列为空的标记,

为了简便起见,本文的实现通过将tail永远指向queue的最后一个元素的下一个元素空间位置,即所谓的留出最后一个的元素空间作为标记;

1. 初始化 queue.head == queue.tail 为空; (tail始终指向队列中最后一个元素的下一个位置);

2. enqueue: 元素入队,(因为tail指向的一个节点的元素空间总是预留的), 是否需要环形调整,queue是否已满(++tail == head),队满增加存储空间,调整队列;

3. dequeue:  队列不为空,将对头元素出对,是否需要环形调整,预留空间是否过多,如果是做相应的调整。

4.队列的销毁;

注意,队列空,队列满的标志。


用动态数组实现的环形队列的代码如下:


1. queue的接口规范文件:queue.h

#ifndef QUEUE_H#define QUEUE_H#include <stdio.h>#include <stdlib.h>#include <string.h>/* initial queue capacity in terms of elements */#defineQUEUE_INITIAL_SIZE1 //1024; 1 just used to test in case;#define CHECK_MEM(p) \if ((p) == NULL) { \    fprintf(stderr, "out of memory: in file %s, line %d, function %s.\n", __FILE__, __LINE__, __FUCTION__); \    exit(1); \}typedef struct queue_t {    void    *base;    void    *head;              /* head points to oldest element */    void    *tail;              /* tail points to the next element position to the earliest element */    int    element_size;    /* element size */    int    capacity;        /* capacity */} queue;/* queue operations */void queue_init(queue *queue, int element_size);void queue_free(queue *queue);int    queue_empty(queue *queue);void   enqueue(queue *queue, void *element);void * dequeue(queue *queue);int    queue_size(queue *queue);void   queue_clear(queue *queue);#endif  /* QUEUE_H */


2. queue功能实现代码:queue.c

#include "queue.h"/* queue operations */void queue_init(queue *queue, int element_size) {    queue->base = (void *) malloc(QUEUE_INITIAL_SIZE * element_size);    if (queue->base == NULL) {        fprintf(stderr, "out of memory (in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);        exit(1);    }    queue->head = queue->base;    queue->tail = queue->base;    queue->element_size = element_size;    queue->capacity = QUEUE_INITIAL_SIZE * element_size;}void queue_free(queue *queue) {    if (queue->base != NULL) {        free(queue->base);        queue->base = NULL;    }    queue->head = NULL;    queue->tail = NULL;    queue->element_size = 0;    queue->capacity = 0;}int queue_empty(queue *queue) {    return (queue->head == queue->tail) ? 1 : 0;}void enqueue(queue *queue, void *element) {    void *newbase;    int n;    memcpy(queue->tail, element, queue->element_size);    queue->tail += queue->element_size;    if (queue->tail == (queue->base + queue->capacity)) {        queue->tail = queue->base;    }    /* queue not full, done */    if (queue->tail != queue->head) return;    /* queue is full, allocate more memory and move data */    newbase = (void *) malloc(queue->capacity << 1);    if (newbase == NULL) {        fprintf(stderr, "out of memory (in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);        queue_free(queue);        exit(1);    }    n = queue->base + queue->capacity - queue->head;    memcpy(newbase, queue->head, n);    if(queue->tail > queue->base) {        memcpy(newbase + n, queue->base, queue->tail - queue->base);    }    free(queue->base);    queue->base = newbase;    queue->head = queue->base;    queue->tail = queue->base + queue->capacity;    queue->capacity <<= 1;}void * dequeue(queue *queue) {    void *p;    void *newbase;    if(queue_empty(queue))return NULL;    int byte_size = queue_size(queue) * queue->element_size;    int n;    if(byte_size > QUEUE_INITIAL_SIZE && byte_size < (queue->capacity >> 1) ) {        if(queue->head <= queue->tail) {            n = queue->tail - queue->head;            newbase = (void *) malloc(n);            if (newbase == NULL) {                fprintf(stderr, "memory error: (in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);                queue_free(queue);                exit(1);            }            memcpy(newbase, queue->head, n);        } else {            n = queue->tail + queue->capacity - queue->head;            newbase = (void *) malloc(queue->capacity >> 1);            if (newbase == NULL) {                fprintf(stderr, "memory error: (in file %s : line %d : fuction %s.)\n", __FILE__, __LINE__, __FUNCTION__);                queue_free(queue);                exit(1);            }            int right = queue->base + queue->capacity - queue->head;            memcpy(newbase, queue->head, right);            memcpy(newbase + right, queue->base, queue->tail - queue->base);        }        free(queue->base);        queue->base = newbase;        queue->head = newbase;        queue->tail = newbase + n;        queue->capacity >>= 1;    }    p = queue->head;    queue->head += queue->element_size;    if(queue->head == (queue->base + queue->capacity)) {        queue->head = queue->base;    }    return p;}int queue_size(queue *queue) {    if(queue->head <= queue->tail) {        return  (queue->tail - queue->head) / queue->element_size;    }else {        return (queue->tail + queue->capacity - queue->head) / queue->element_size;    }}/* just clear elements to queue empty, but don't free memory */void queue_clear(queue *queue) {    queue->head = queue->base;    queue->tail = queue->base;}


3. 对queue的测试代码:main.c

#include "queue.h"void printArray(int a[], int len);int main(int argc, char* argv[]) {    int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};    int len = sizeof(a)/sizeof(a[0]);    int i;    queue queue;    printArray(a, len);    queue_init(&queue, sizeof(a[0]));//    printf("queue capacity:%d\n", queue.capacity);//    printf("queue size: %d\n", queue_size(&queue));    for(i = 0; i < len; ++i) {        enqueue(&queue, &a[i]);//         printf("queue capacity:%d\n", queue.capacity);//         printf("queue size: %d\n", queue_size(&queue));    }//    printf("queue capacity:%d\n", queue.capacity);//    printf("queue size: %d\n", queue_size(&queue));    while(!queue_empty(&queue)) {        printf("%d\t", *(int*)dequeue(&queue));//        printf("queue capacity:%d\n", queue.capacity);//        printf("queue size: %d\n", queue_size(&queue));    }    printf("\n");//    printf("queue capacity:%d\n", queue.capacity);//    printf("queue size: %d\n", queue_size(&queue));    queue_free(&queue);    return 0;}void printArray(int a[], int len) {    int i;    for(i=0; i<len; i++) {        printf("%d\t", a[i]);    }    printf("\n");}


用例测试结果:




原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 新鞋鞋底吱吱响怎么办 新鞋鞋底滑了怎么办 工作中同事不配合怎么办 做体力活一身疼怎么办 大脑左则中动脉血管狭窄?怎么办 儿童体质差免疫力差怎么办 nba篮球大师体力不够怎么办 一千米差10秒怎么办 四十岁以后体力和耐力差怎么办 打篮球一打比赛就紧张怎么办 耐克空军鞋鞋底边胶掉了怎么办 鞋底踩到老鼠胶怎么办 头蒙怎么办最快最有效 备孕老公压力大怎么办 宝宝太兴奋不睡怎么办 我很烦只睡三小时觉怎么办才好 柯基精力太旺盛怎么办 孩子学习熬夜精力不足怎么办 肺癌晚期吃不下饭怎么办 这俩天吃药太多肝肾功能不好怎么办 跑步跑得头疼晕怎么办 吃完辣的想吐怎么办 体育生暑假训练太累怎么办 高强度运动后性功能不好怎么办 运动后第二天全身酸痛怎么办 运动后心慌想吐怎么办 激素停后全身疼怎么办 运动完头晕想吐怎么办 跑了步全身酸痛怎么办 运动后全身没力气怎么办 学完游泳不会换气怎么办 猫不吃饭精神不好怎么办 运动完头晕目眩想吐怎么办 酒后第二天恶心想吐怎么办 剧烈运动后肌肉酸痛怎么办 剧烈运动后吐了怎么办 长跑后头晕想吐怎么办 运动后一直想吐怎么办 跑多了恶心想吐怎么办 剧烈运动恶心想吐怎么办 长跑之后 恶心想吐怎么办