数据结构-队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。队列的实现有顺序队列、循环队列和链表队列。这里我用了循环队列和链表队列两种。

顺序队列:
与顺序表一样,顺序队列需要分配一块连续的区域来存储队列的元素,需事先定义数据大小。当队列满入队是会出现上溢的现象,队列空出队会产生下溢的想象。这是后要想继续操作,需要对数据进行移动,效率不佳。

循环队列:
循环队列多使用一个数据大小的空间用来表示队列空或者队列满。也就是说循环队列的存储空间中最大数据个数加一(倘若不牺牲着一个数据大小的空间,就需要额外声明一个标志位flag。初始情况下flag=0,front=rear表示队列空。第二次front=rear,flag=1,表示队列满)。循环队列中中有三种状态:

  1. front==rear ( 队列为空状态 )
  2. front!=(rear+1)%maxSize ( 队列的一般状态 )
  3. front==(rear+1)%maxSize ( 队列为满的状态 )

如下图所示,循环队列中能存取的最大数据个数为7个,但需要申请8个数据大小的空间。第一种情况中:队列中没有数据,此时front=rear=0,队列为空;第二种情况中:队列中有一个数据,front=0、rear=1,队列处于一般状态,既能进队也能出队;第三种情况:队列满,front=0,rear=7,此时满足front=(rear+1)%maxSize。在队列常用的操作:打印、入队、出队、获取队头、队尾数据值中。打印、入队、出队、获取队尾数据值中要注意该队列是循环队列,可能出现rear>front的情况,需要处理一下。




代码:

#include<iostream>
using namespace std;
class arrayQueue
{
    int front;
    int rear;
    int* queue;
    int maxSize;
public:
    arrayQueue() {}
    arrayQueue(int maxS) 
    {
        front = rear = 0;
        queue = new int[maxS+1];
        maxSize = maxS+1;
    }
    ~arrayQueue()
    {
        del();
    }
    void dis();//打印队列元素
    void del();//删除
    void push(int item);//item入队
    void pop();//出队
    void creat(int num);//创建num个元素的测试队列

    bool isEmpty();//是否空
    bool isFull();//是否空
    bool getFront(int &val);//读取队头元素
    bool getRear(int &val);//读取队尾元素
};
void arrayQueue::dis()
{
    if (!isEmpty())
    {
        for (int i = front;i != rear;i=(i+1)%maxSize)
        {
            if ((i + 1) % maxSize != rear)
            {
                cout << queue[i] << "->";
            }
            else
                cout << queue[i] << endl;
        }
    }
    else
        cout << "队列空。" << endl;
}
void arrayQueue::del()
{
    delete[] queue;
    front = rear = maxSize = 0;
}
void arrayQueue::push(int item)
{
    if (!isFull())
    {
        queue[rear] = item;
        rear =(rear+1)%maxSize;
    }
    else
    {
        cout << "队列满。" << endl;
    }
}
void arrayQueue::pop()
{
    if (!isEmpty())
    {
        front = (front +1) % maxSize;
    }
    else
    {
        cout << "队列空。" << endl;
    }
}
void arrayQueue::creat(int num)
{
    for (int i = 0;i < num;i++)
        push(i+1);
}
bool arrayQueue::isEmpty()
{
    return front == rear;
}
bool arrayQueue::isFull()
{
    return (rear + 1) % maxSize == front;
}
bool arrayQueue::getFront(int& val)
{
    if (!isEmpty())
    {
        val = queue[front];
        return true;
    }
    else
    {
        cout << "队列空。" << endl;
        return false;
    }
}
bool arrayQueue::getRear(int& val)
{
    if (!isEmpty())
    {
        val = queue[(rear-1+maxSize)%maxSize];
        cout << val << endl;
        return true;
    }
    else
    {
        cout << "队列空。" << endl;
        return false;
    }
}

int main()
{
    int a;
    arrayQueue t(20);
    t.creat(20);
    t.dis();
    return 0;
}

链表队列:
链式队列是基于单链表的存储表示,队头指针front指向队头结点,队尾指针rear指向队尾结点。链表中所有的结点都必须通过这两个指针访问到,并且队头端只能用来删除结点,队尾端用来插入结点。如下图所示:n个元素的队列中,队头指针指向链表中第一个数据、队尾指针指向链表中最后一个数据,其中出、入队方向就是箭头描述的方向。




代码:

#include<iostream>
using namespace std;
class queNode
{
public:
    int element;
    queNode* next;

    queNode() {}
    queNode(int e, queNode* n) :element(e), next(n) {}
};
class queList
{

public:
    queNode* front;
    queNode* rear;
    int length;

    queList() {}
    ~queList()
    {
        del();
    }

    void dis();//打印队列元素
    void del();//删除
    void push(int item);//item入队
    void pop();//出队
    void creat(int num);//创建测试队列

    bool isEmpty();//是否空
    bool getFront(int &val);//读取队头元素
    bool getRear(int &val);//读取队尾元素


};
void queList::dis()
{
    if (!isEmpty())
    {
        queNode* t = front;
        while (t != NULL)
        {
            if (t->next != NULL)
            {
                cout << t->element<< "<-";
            }
            else
            {
                cout << t->element << endl;
            }
            t = t->next;
        }
    }
    else
    {
        cout << "队列空。" << endl;
    }
}
void queList::del()
{
    if (!isEmpty())
    {
        while (front != NULL)//每轮循环开始时,t与front的值相等,不存在访问空指针内容
        {
            rear = front;
            front = front->next;
            delete(rear);
        }
        rear = NULL;
        length = 0;
    }
}
void queList::push(int item)
{
    queNode* newNode = new queNode(item, NULL);
    if (length != 0)
    {
        rear->next = newNode;
        rear = newNode;
    }
    else
    {
        front = rear = newNode;
    }
    length += 1;
}
void queList::pop()
{
    if (!isEmpty())
    {
        queNode* t = front;
        front = front->next;
        length -= 1;
        if (length == 0)
            rear = NULL;
        delete(t);
    }
}
void queList::creat(int num)
{
    if (num > 0)
    {
        for (int i = 1;i <= num;i++)
            push(i);
    }
}
bool queList::isEmpty()
{
    return (length == 0);
}
bool queList::getFront(int& val)
{
    if (!isEmpty())
    {
        val = front->element;
        return true;
    }
    else
        return false;
}
bool queList::getRear(int& val)
{
    if (!isEmpty())
    {
        val = rear->element;
        return true;
    }
    else
        return false;
}

int main()
{
    queList t;
    t.creat(10);
    t.dis();
    return 0;
}

链式队列中发现了一个以前一直没发现的问题。当一个指针指向的空间已经被释放后,它的值是什么?访问它会怎么样?它的值还是被释放掉的那块空间的地址,访问它程序会崩溃。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值