循环队列的基本结构如下:
front 属性 表示 队头,rear 属性表示 队尾。
在队空时 :q.rear 和 q.front 都为0 ,其余时刻q.rear 指向 队尾的后继节点,q.front指向 队头.
当在队尾插入元素时,q.rear + 1 ,在删除 队头元素时 ,q.front + 1,这样的操作 会造成 “假溢出”问题。
图(d) 就是一种 假溢出 问题,q.rear 指向 空间的边界,再插入 会造成 溢出,但是 实际上 空间 并未满。
为了解决假溢出,将 队列 看成 一个 环。下面上图:
当队列成为一个循环队列时 有两个问题:
1. 当队空 和 队满时, q.front 都等于 q.rear;这样就无法区分 队空 和 队满的 情况。解决这个问题 有两个方法:
(1) 设置 一个 标志位,来区分 是队空,还是队满。
(2) 少用一个元素空间(最高地址元素),判断 队头指针在 队尾指针的下一个位置上就是队满。
下面的代码用的是第一个方法,设置了一个 队列长度 len 属性 来 判断 队空,队满。
2. 当 队满时,不能像 顺序表一样 重新 分配 一个更大的 空间。所以 如果 不知道 队列的 最大空间,请 使用 链表,或者 非循环队列。非循环队列 在出队时, 队头位置不动,而是移动元素位置,并将 队尾位置减1.
下面贴出我的代码,欢迎指出代码不足
// SequenceQueue.cpp : 循环队列的算法实现。 // #include "stdafx.h" #include <stdlib.h> ////队列最大分配数 #define QUEUE_MAX_SIZE 10//为了测试 故意将值设置很小 typedef int ElementType; enum E_State { E_State_Error = 0, E_State_Ok, }; //循环队列数据结构 struct Queue { ElementType * base;//堆分配基址 int front;//队头索引,指向队头节点 int rear;//队尾索引,指向队尾节点的后继结点 int len;//队长 }; E_State queueInit(Queue * queue){ queue->base = (ElementType *) malloc(sizeof(ElementType) * QUEUE_MAX_SIZE); if (queue->base != NULL) { queue->front = queue->rear = 0; queue->len = 0; return E_State_Ok; } else { return E_State_Error; } } void queueClear(Queue * q){ q->front = q->rear = 0; q->len = 0; } void queueDestory(Queue * q){ queueClear(q); free(q->base); q->base = NULL; } bool queuEmpty(Queue q){ return q.len == 0 ? true : false; } int queueLen(Queue q){ return q.len; } //入队 E_State enqueue(Queue * q,ElementType data){ if (q->len >= QUEUE_MAX_SIZE) { printf("队满,插入无效\n"); return E_State_Error; } q->base[q->rear] = data; q->rear = (q->rear +1)% QUEUE_MAX_SIZE; q->len++; return E_State_Ok; } //出队 E_State dequeue(Queue * q,ElementType * data){ if (q->len > 0)//栈不为空 { *data = q->base[q->front]; q->front = (q->front + 1) % QUEUE_MAX_SIZE; q->len --; return E_State_Ok; } return E_State_Error; } void queueTraverse(Queue q){ printf("--------队列遍历开始----------\n"); if (q.len > 0)//队列非空 { int index = q.front; //用do while 排除了 队满的情况。。。 do { printf("----------%d-----------\n",q.base[index]); index = (index+1)%QUEUE_MAX_SIZE; } while (index != q.rear); } printf("--------队列遍历结束----------\n"); } int _tmain(int argc, _TCHAR* argv[]) { Queue queue; queueInit(&queue);//初始化 enqueue(&queue,1);//入队 ElementType data; dequeue(&queue,&data);//出队 for (int i = 1; i <= QUEUE_MAX_SIZE+1; i++)//故意入满,还入队 { enqueue(&queue,i); } dequeue(&queue,&data); dequeue(&queue,&data);//出队 queueTraverse(queue); char * s = queuEmpty(queue) ? "空" : "不为空"; printf("队列长度为:%d\n队列是否为空:%s",queueLen(queue),s); queueDestory(&queue); return 0; }
原文地址:http://blog.csdn.net/fuming0210sc/article/details/44098961