本文主要给出我对队列的实现,包括顺序队列和链队列。
顺序队列
顺序队列是用数组存放队列元素,同时设置队头和对尾指针来控制元素的出队和入队。约定:
- 队头指针front指向队头元素,
- 队尾指针rear指向队尾元素的下一个
由于单纯的顺序队列存在“假溢出”的现象,即指针是单向移动的,当front在高地址的时候,其实低地址的空间也可以使用。所以,考虑采用循环队列的形式来实现。循环队列是将存储队列的数组看成头尾相接的循环结构,从而地段低端地址也可以得到有效的使用。
在循环队列中,浪费一个数组元素空间的情况下:
- 队空的条件是 : front == rear;
- 队满的条件是:(rear + 1) % QUEUE_SIZE = front
- 队列的长度是:(rear - front + QUEUE_SIZE) % QUEUE_SIZE
需要特别注意的是,循环队列队头和队尾指针的移动,都要在循环意义下 + 1 即:
- front = (front + 1) % QUEUE_SIZE
- rear = (rear + 1) % QUEUE_SIZE
common.h
#ifndef common_H
#define common_H
/* 函数结果状态码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//#define OVERFLOW -2
//#define UNDERFLOW -3
/* 类型定义 */
typedef int Status; // Status是函数的类型,其值是函数结果状态码
typedef int ElemType; // ElemType是数据类型
#endif
Queue.h
#ifndef Queue_H
#define Queue_H
#define QUEUE_SIZE 1024
#include "common.h"
#include
// 循环队列结构定义
struct Queue{
ElemType data[QUEUE_SIZE];
int front; // 头指针
int rear; // 尾指针
Queue(){ std::memset( this, 0, sizeof(Queue) ); }
};
// 循环队列基本操作
Status push( Queue& que, ElemType x );
Status pop( Queue& que );
ElemType front( Queue& que );
ElemType back( Queue& que );
int size( Queue& que );
bool empty( Queue& que );
#endif
Status push( Queue& que, ElemType x ){
if( (que.rear + 1)%QUEUE_SIZE == que.front ){
std::cerr << "Overflow";
return OVERFLOW;
}
else{
que.data[ que.rear ] = x;
que.rear = ( que.rear + 1 )%QUEUE_SIZE; // 循环意义下+1
return OK;
}
}
Status pop( Queue& que ){
if( que.front == que.rear ){
std::cerr << "Underflow";
return UNDERFLOW;
}
else{
que.front = (que.front + 1)%QUEUE_SIZE; // 循环意义下+1
return OK;
}
}
ElemType front( Queue& que ){
if( que.front == que.rear ){
std::cerr << "Underflow";
return UNDERFLOW;
}
else{
return que.data[que.front];
}
}
ElemType back( Queue& que ){
if( que.front == que.rear ){
std::cerr << "Underflow";
return UNDERFLOW;
}
else{
return que.data[ (que.rear - 1)%QUEUE_SIZE ];
}
}
int size( Queue& que ){
return (que.rear - que.front + QUEUE_SIZE)%QUEUE_SIZE;
}
bool empty( Queue& que ){
return que.front == que.rear;
}
链队列
顺序队列是用链表存放队列元素,同时设置队头和对尾指针来控制元素的出队和入队。约定:
- 队头指针front指向队头元素的前一个,即指向头结点
- 队尾指针rear指向队尾元素
common.h
#ifndef common _H
#define common_H
/* 函数结果状态码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//#define OVERFLOW -2
//#define UNDERFLOW -3
/* 类型定义 */
typedef int Status; // Status是函数的类型,其值是函数结果状态码
typedef int ElemType; // ElemType是数据类型
#endif
LinkedQueue.h
#ifndef LinkedQueue_H
#define LinkedQueue_H
#include "common.h"
#include
#include
// 链队列节点结构声明
struct ListNode{
ElemType data;
ListNode* next;
ListNode() { std::memset(this, 0, sizeof(ListNode)); }
ListNode( ElemType x ) : data(x), next(NULL) {}
};
// 链队列结构声明
struct LinkedQueue{
ListNode* front; // front指向队首前一个元素即头结点
ListNode* rear; // rear指向队尾元素
LinkedQueue(){
front = new ListNode; // 增加头结点
rear = front;
}
virtual ~LinkedQueue(){
delete front;
}
};
// 链队列基本操作
Status push( LinkedQueue& que, ElemType x );
Status pop( LinkedQueue& que );
ElemType front( LinkedQueue& que );
ElemType back( LinkedQueue& que );
int size( LinkedQueue& que );
bool empty( LinkedQueue& que );
#endif
Status push( LinkedQueue& que, ElemType x ){
ListNode* s = new ListNode(x);
if(!s){
std::cerr << "Not enough space!";
return ERROR;
}
que.rear->next = s;
que.rear = s;
return OK;
}
Status pop( LinkedQueue& que ){
ListNode* s = que.front->next;
if(!s){
std::cerr << "Underflow";
return UNDERFLOW;
}
else{
que.front->next = s->next;
delete s;
return OK;
}
}
ElemType front( LinkedQueue& que ){
ListNode* s = que.front->next;
if(!s){
std::cerr << "Underflow";
return UNDERFLOW;
}
else{
return s->data;
}
}
ElemType back( LinkedQueue& que ){
ListNode* s = que.rear;
if(!s){
std::cerr << "Underflow";
return UNDERFLOW;
}
else{
return s->data;
}
}
int size( LinkedQueue& que ){
ListNode* p = que.front->next;
int cnt = 0;
while(p){
++cnt;
p = p->next;
}
return cnt;
}
bool empty( LinkedQueue& que ){
return que.front == que.rear;
}