如何使用C语言写: Generic Queue

Model

------------------------------------------------------------------------------------------------------------------------


队列也是限制插入和删除位置的表.

主要操作是enqueuedequeue操作.

enqueue:入队操作.在表的队尾(rear)插入一个元素.

dequeue:出队操作.删除表的队首(front)元素.

 

本文使用循环数组实现GenericQueue.需要指定capacity.缺点是超出容量,无法动态增长.当然,可以仿照list的方式克服这个问题.

 完整代码详见我的github(https://github.com/gnudennis/ds_c)(genric-queue.h generic-queue.c generic-queue-test.c)

 

核心代码

------------------------------------------------------------------------------------------------------------------------

0. Generic Queue定义

typedef void *ElementAddr;
typedef void (*PfCbFree)(ElementAddr);

typedef struct QueueRecord
{
        ElementAddr	*array;
        int		capacity;
        int		elemsize;
        int		front;
        int		rear;
        int		size;
        PfCbFree	freefn;
} *Queue;

1. API

/* Create a new queue */
Queue queue_create(int elemsize, int capacity, PfCbFree freefn);

/* Dispose the queue */
void queue_dispose(Queue que);

/* Make the give queue empty */
void queue_make_empty(Queue que);

/* Return true if the queue is empty */
int queue_is_empty(Queue que);

/* Return true if the queue is full */
int queue_is_full(Queue que);

/* Insert a new element onto queue */
void queue_enqueue(Queue que, ElementAddr elemaddr);

/* Delete the front element off the queue */
void queue_dequeue(Queue que);

/* Fetch the front element from the queue */
void queue_front(Queue que, ElementAddr elemaddr);

/* Fetch and Delete the front element from the queue */
void queue_front_and_dequeue(Queue que, ElementAddr elemaddr);

2.Implementation

/* Create a new queue with capacity */
Queue 
queue_create(int elemsize, int capacity, PfCbFree freefn)
{
        Queue que;

        que = malloc(sizeof(struct QueueRecord));
        if ( que == NULL ) {
                fprintf(stderr, "Out of memory\n");
                exit(1);
        }
        
        que->elemsize = elemsize;
        que->capacity = capacity > MIN_QUEUE_SIZE ? capacity : MIN_QUEUE_SIZE;

        que->array = malloc(elemsize * que->capacity);
        if ( que->array == NULL ) {
                fprintf(stderr, "Out of memory\n");
                exit(1);
        }
        que->front = 1;
        que->rear = 0;
        que->size = 0;
        que->freefn = freefn;

        return que;
}

/* Dispose the queue */
void 
queue_dispose(Queue que)
{
        if (que != NULL) {
                queue_make_empty(que);
                free(que->array);
                free(que);
        }
}

/* Make the give queue empty */
void 
queue_make_empty(Queue que)
{
        if ( que->freefn ) {
                int i;
                for ( i = 0; i < que->size; ++i) {
                        free((char *)que->array + 
                             que->elemsize * i);
                }
        }
        que->size = 0;
        que->front = 1;
        que->rear = 0;
}

/* Return true if the queue is empty */
int 
queue_is_empty(Queue que)
{
        return que->size == 0;
}

/* Return true if the queue is full */
int 
queue_is_full(Queue que)
{
        return que->size == que->capacity;
}

static int 
successor(Queue que, int index)
{
        if ( ++index == que->capacity)
                index = 0;
        return index;
}

/* Insert a new element onto queue(rear) */
void 
queue_enqueue(Queue que, ElementAddr elemaddr)
{
        void *target;

        if ( queue_is_full(que) ) {
                fprintf(stderr, "Full queue\n");
                exit(1);
        }
        que->rear = successor(que, que->rear);
        target = (char *)que->array + que->elemsize * que->rear;
        memcpy(target, elemaddr, que->elemsize);
        que->size++;
}

/* Delete the front element off the queue */
void 
queue_dequeue(Queue que)
{
        if ( queue_is_empty(que) ) {
                fprintf(stderr, "Empty queue\n");
                exit(1);
        }
        if ( que->freefn ) {
                void *target = (char *)que->array +
                               que->front * que->elemsize;
                que->freefn(target);
        }
        que->size--;
        que->front = successor(que, que->front);
}

/* Fetch the front element from the queue */
void 
queue_front(Queue que, ElementAddr elemaddr)
{
        void *target = (char *)que->array + 
                       que->front * que->elemsize;
        memcpy(elemaddr, target, que->elemsize);
}

/* Fetch and Delete the front element from the queue */
void 
queue_front_and_dequeue(Queue que, ElementAddr elemaddr)
{
        void *target;

        if ( queue_is_empty(que) ) {
                fprintf(stderr, "Empty queue\n");
                exit(1);
        }

        target = (char *)que->array + 
                       que->front * que->elemsize;
        memcpy(elemaddr, target, que->elemsize);

        que->size--;
        que->front = successor(que, que->front);
}

分析

----------------

本文使用循环数组实现GenericQueue.需要指定capacity.既然是循环数组,就是围成一个圈.也就插入第一个元素没有必要非要放在0处啦.

初始状态:

{

que->size = 0;

que->front = 1;

que->rear = 0;

}

说明这样第一次enqueue操作放在array[1],当然:这不是必须的,取决于你想放在那里.

#define mxx

{

que->size = 0;

que->front =m+1;

que->rear = m;

}

就放在array[m+1].



你可能感兴趣的:(数据结构)