c++之数据结构——队列(queue)

关于队列的基本概念以及基本操作的c++实现

    • 队列的定义
    • 队列的基本理论
    • 队列的图解
    • 队列的基本操作
    • 队列的三种形式及其c++实现(以整型为例)
      • -顺序队列
      • -循环队列
      • -链式队列
        • 1.有头节点
        • 2.无头结点

(发表日期:2020/7/7)

队列的定义

队列是一种最基本的数据结构,是一种只能在一端插入,另一端删除的特殊的线性表。

队列的基本理论

  • 进行插入操作的一端称为队尾(rear),进行删除操作的端称为队头(front)
  • 队列的插入操作叫做入队,删除操作叫做出队
  • 队列的特点:先进先出,故队列又称为先进先出(FIFO—first in first out)线性表。

举个简单的例子:
中午放学了,同学们都到食堂去排队打饭,他们按照先来后到的顺序排成一列(形成了一个队列),最后来的同学站在队伍的最后端(队尾),最先过来的同学(队头)站在队伍的最前端,这位同学打完饭之后就离开了(出队),轮到他后面的一个同学继续打饭(成为了新的队头),这时,又来了一位同学,但他只能站在队伍的最后端等待(入队,成为新的队尾)前面的同学先打饭。

队列的图解

  • 每次出队时,队头元素出队,它的相邻元素成为新的队头元素。
  • 每次入队时,目标元素加入到队列尾部并成为新的队尾元素。

当前队列:
c++之数据结构——队列(queue)_第1张图片


入队:
在队列尾部入队,并成为队尾
c++之数据结构——队列(queue)_第2张图片


出队:
队头元素出队,相邻元素称为新的队头
c++之数据结构——队列(queue)_第3张图片

队列的基本操作

  • 初始化(queue):设置队列为空
  • 判空(isEmpty):判断队列是否为空
  • 判满(isFull)<仅对顺序(循环)队列>:判断队列是否已满
  • 取队头元素(getFront):取出队头元素
    ——条件:队列不为空
  • 取队尾元素(getBack):取出队尾元素
    ——条件:队列不为空
  • 得到队列长度(getLength):返回队列中元素个数
  • 入队(push):将元素入队到队列尾部,称为新的队尾
  • 出队(pop):将队头元素出队,队头右移一位
  • 队列的析构(~queue)<仅对链式队列>:释放队列中元素的内存空间

队列的三种形式及其c++实现(以整型为例)

-顺序队列

顺序表(数组)作为队列的存储结构:
c++之数据结构——队列(queue)_第4张图片

c++代码实现:

#include
using namespace std;
const int MAXSIZE=1000;
class queue{
public: 
    queue(){	//初始化
        front=0;
        back=-1;
        count=0;
    }
    bool isEmpty(){	//判空
        if(count==0){
            cout<<"queue is empty.\n";
            return true;
        }
        return false;
    }
    bool isFull(){	//判满
        if(count==MAXSIZE||back==MAXSIZE-1){
            cout<<"queue is full.\n";
            return true;
        }
        return false;
    }
    int getFront(){	//取队头
        if(isEmpty()){
            return -1;
        }
        return data[front];
    }
    int getBack(){	//取队尾
        if(isEmpty()){
            return -1;
        }
        return data[back];
    }
    bool push(int num){	//入队
        if(isFull()){
            return false;
        }
        back++;
        data[back]=num; 
        count++;
        return true;
    }
    bool pop(){	//出队
        if(isEmpty()){
            return false;
        }
        front++;
        count--;
        return true;
    }
    int getLength(){	//得到队列长度
        return count;
    }
private:
    int front;
    int back;
    int count;
    int data[MAXSIZE];
};

-循环队列

顺序队列的基础上进行了空间使用率的优化。

前面提到的顺序队列,当队尾移动到顺序表的最后一个位置时,队列被判断为已满,此时如果队列前端的某部分元素已经出队,那么顺序表的前端会空余出部分空间未使用而造成浪费

要解决这个问题,我们使用循环队列的思想进行优化:

我们利用想象,把顺序表弯曲并将两端连起来,此时顺序表变成了一个,当队尾移动到原来顺序表的最后一个位置时,若此时原来顺序表前端位置有空余,那么在进行入队操作时,将新入队的元素放到顺序表的前端作为新的队尾。

这样我们就实现了一个循环队列
(红色线条表示原顺序表两端重合)
c++之数据结构——队列(queue)_第5张图片

接下来我们进行两次入队操作:
第一次:
c++之数据结构——队列(queue)_第6张图片
第二次:

此时在原顺序表中,队尾已经到队头的前面来了,原表前端空余部分再次被使用。

c++之数据结构——队列(queue)_第7张图片

c++代码实现:
(基于顺序队列代码,对判满(isFull)、入队(push)、出队(pop)进行了修改)

#include
using namespace std;
const int MAXSIZE=1000;
class queue{
public: 
    queue(){	//初始化
        front=0;
        back=-1;
        count=0;
    }
    bool isEmpty(){	//判空
        if(count==0){
            cout<<"queue is empty.\n";
            return true;
        }
        return false;
    }
    bool isFull(){	//判满
        if(count==MAXSIZE){
            cout<<"queue is full.\n";
            return true;
        }
        return false;
    }
    int getFront(){	//取队头
        if(isEmpty()){
            return -1;
        }
        return data[front];
    }
    int getBack(){	//取队尾
        if(isEmpty()){
            return -1;
        }
        return data[back];
    }
    bool push(int num){	//入队
        if(isFull()){
            return false;
        }
        back=(back+1)%MAXSIZE;	//实现循环
        data[back]=num; 
        count++;
        return true;
    }
    bool pop(){	//出队
        if(isEmpty()){
            return false;
        }
        front=(front+1)%MAXSIZE;	//实现循环
        count--;
        return true;
    }
    int getLength(){	//得到队列长度
        return count;
    }
private:
    int front;
    int back;
    int count;
    int data[MAXSIZE];
};

-链式队列

以结构体链表作为队列的储存结构:
有两种方式:

  1. 有头结点:设置一个附加的头节点指向队头元素,头节点一直存在且不改变,入队操作不用分情况
  2. 无头节点:头结点就是队头元素,队列为空时头节点为空,在入队操作时要分情况插入

1.有头节点

-初始状态:
在这里插入图片描述

-插入结点后:
c++之数据结构——队列(queue)_第8张图片

c++代码实现:

#include
using namespace std;
struct node{	//队列结点
    int data;
    node *next;
};
class queue
{
public:
    queue(){	//初始化
        head=new node;
        head->next=NULL;
        last=head;
        count=0;
    }
    ~queue(){
        while(head->next!=NULL){
            pop();
        }
        delete head;	//释放head
    }
    bool isEmpty(){	//判空
        if(count==0){
            cout<<"queue is empty.\n";
            return true;
        }
        return false;
    }
    void push(int num){	//入队,无需对空列表特殊处理
        count++;
        node *newNode=new node;
        newNode->data=num;
        newNode->next=NULL;
        last->next=newNode;
        last=newNode;
    }
    bool pop(){	//出队
        if(isEmpty()){
            return false;
        }
        count--;
        node *n=head->next;
        head->next=n->next;
        delete n;
        if(head->next==NULL){	//当删除的结点为最后一个结点时
            last=head;
        }
        return true;
    }
    int getFront(){	//取队头
        if(isEmpty()){
            return -1;
        }
        return head->next->data;
    }
    int getLength(){	//得到队列长度
        return count;
    }
    int getBack(){	//取队尾
        if(isEmpty()){
            return -1;
        }
        return last->data;
    }
private:
    int count;
    node *head;
    node *last;
};

2.无头结点

-初始状态:
在这里插入图片描述

-插入结点后:
c++之数据结构——队列(queue)_第9张图片
c++代码实现:

#include
using namespace std;
struct node{	//队列结点
    int data;
    node *next;
};
class queue
{
public:
    queue(){	//初始化
        front=NULL;
        last=NULL;
        count=0;
    }
    ~queue(){	//析构,释放结点空间
        while(front!=NULL){
            pop();
        }
    }
    bool isEmpty(){	//判空
        if(count==0){
            cout<<"queue is empty.\n";
            return true;
        }
        return false;
    }
    void push(int num){	//入队,分空队列和非空队列两种情况
        if(isEmpty()){	//空队列时
            count++;
            node *newNode=new node;
            newNode->data=num;
            newNode->next=NULL;
            last=newNode;
            front=newNode;
            return;
        }
        //非空队列时
        count++;
        node *newNode=new node;
        newNode->data=num;
        newNode->next=NULL;
        last->next=newNode;
        last=newNode;
    }
    bool pop(){	//出队
        if(isEmpty()){
            return false;
        }
        count--;
        node *n=front;
        front=front->next;
        delete n;
        return true;
    }
    int getFront(){	//取队头
        if(isEmpty()){
            return -1;
        }
        return front->data;
    }
    int getLength(){	//得到队列长度
        return count;
    }
    int getBack(){
        if(isEmpty()){	//取队尾
            return -1;
        }
        return last->data;
    }
private:
    int count;
    node *front;
    node *last;
};

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