队列的实现-顺序队列和链队列

本文主要给出我对队列的实现,包括顺序队列和链队列。

顺序队列(循环队列)

基本概念

顺序队列

顺序队列是用数组存放队列元素,同时设置队头和对尾指针来控制元素的出队和入队。约定:

  • 队头指针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 <cstring>

// 循环队列结构定义
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

顺序队列基本操作(Queue.cpp)

  • 入队
    思路:注意上溢
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 <cstdlib>
#include <cstring>

// 链队列节点结构声明
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

链队列基本操作(LinkedQueue.cpp)

  • 入队
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;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值