首先队列成员是先进先出(first in first out,FIFO)的,即添加数据只能从后面添加,而删除数据只能从第一位删除。y
如果用简单的数组来存储数据,那么每删除一个数据就要把所有项向前移动一位,理论上也可行,实现起来也较为简单,但这里我们用另外一种方式——链表。
一个链表是由各个节点构成的,每个节点存储了一个数据和一个指向下一个节点的指针每个节点可以用结构体来实现即:
struct Node
{
int i;//这里是每个节点存储的数据,这里以一个int为例,当然你也可以添加更多的数据
struct Node *next;//这是一个指向下一个Node结构体(节点)的指针,显然从声明也可以看出来next是一个Node类型指针
}
这样在一个队列中我们就可以只保存第一个和最后一个节点的指针;
Node *front//它指向第一个结构体
Node *rear//它指向最后一个结构体
我们所要建立的队列应当满足以下功能:
- 创建一个含有n个数据的队列
- 向队列最后添加数据
- 删除第一个数据(同时获得该数据)
- 通过’[]'获取数据
- 能够获取总数据的个数
#include<iostream>
class queue
{
private:
struct node//节点定义
{
int i;
struct node *next;
};
node *front;//指向第一个结构体
node *rear;//指向最后一个结构体
enum
{
SIZE = 10
};
int curr_number;//保存队列当前数据的个数
const int toll_numbers;//队列能保存的数据总个数
queue(const queue &que) : toll_numbers(0){};
queue operator=(const queue &que) { return *this; };//将复制构造函数和赋值操作符放置在私有区域,避免队列对象使用这两种函数,因为我们还不打算实现此功能;
public:
queue(const int num = SIZE);//构造函数,并提供一个默认值
~queue();//析构函数
bool enqueue(const int &i);//添加数据
bool dequeue(int &i);//删除数据
int size() const;//返回当前元素个数
int operator[](int odn);//用[]访问数据
};
int main()
{
int a, b, c, d;
queue q(3);//创建队列,这个队列只能放3个数据
//向队列添加数据
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
//查看队列大小和访问元素
std::cout << q.size() << std::endl;
std::cout << q[2] << std::endl;
//删除元素,并将删除的元素放到a,b,c中
q.dequeue(a);
q.dequeue(b);
q.dequeue(c);
//测试能否再删
if (!q.dequeue(d))
{
std::cout << "delete failure" << std::endl;
}
//查看a,b,c的值
std::cout << a << b << c;
}
//函数定义
queue::queue(const int num):toll_numbers(num)
{
front = nullptr;
rear = nullptr;//新建的队列没有任何成员,front,rear为空指针
curr_number = 0;//队列当前元素个数为0
}
queue::~queue()
{
node *temp;//用来存储front传给他的第一个数据的指针,以便在front改为指向下一个元素时删除第一个数据
while (front != nullptr)
{
temp = front;//保存第一个数据的地址
front = front->next;//让front指向下一个数据
delete temp;//删除前一个数据
}
}
bool queue::enqueue(const int & i)
{
if(toll_numbers == curr_number)
return false;//如果队列满了,添加失败,函数体结束,返回false
curr_number++;//队列元素个数加一
node *add = new node;//创建新的节点的指针,他将成为这个队列里最后一个元素
add->i = i;
add->next = nullptr;//初始化这个节点
if(front==nullptr)
front = add;//如果这是一个空队列,让front指向它
else
rear->next = add;//如果不是空队列,让原本的最后一个节点指向它
rear = add;//然后让rear指向新添加的节点
return true;
}
bool queue::dequeue(int & i)
{
if(front == nullptr)//如果是个空队列,删除失败,返回false,函数体结束
return false;
i = front->i;//将第一个元素保存在i中
node *temp = front;//用来存储front传给他的第一个数据的指针,以便在front改为指向下一个元素时删除第一个数据
front = front->next;//让front指向下一个数据
delete temp;//删除前一个数据
curr_number--;//更新当前元素数量
if(curr_number == 0)//如果删除了一个元素后变成了空队列,那么指向最后一个元素的指针也得改为空指针,因为它指向的节点被删除了
rear = NULL;
return true;
}
int queue::size() const//返回当前元素个数
{
return curr_number;
}
int queue::operator[](int odn)
{
if(curr_number == 0)//如果它是一个空队列,那么对他用[]将没有意义,不判断的话,不知道会发生什么,可能会引发各种不确定错误
return 0;
int count = 0;//习惯上从0开始计数,当然你也可以从一开始
node *temp;
temp = front;
while(count != odn)
{
temp = temp->next;
count++;
}
return temp->i;
}
现在这个队列虽然已经实现了一些最基本功能,但它仍然还不是一个成熟的队列,还需要很多很多改进的地方!