队列的浅析(C++)

队列和上篇提到的栈类似,本质上都是特殊的线性表,它是在一端(队头)进行删除操作,另一端(队尾)进行插入操作,遵守先进先出的规则。。

既然队列也是线性表,当然也有两种数据存储方式:

顺序存储结构:这种结构事先要基本确定队列的大小,不支持动态分配存储空间,所以插入和删除元素比较省时,但是会造成空间的浪费。

                     为了节省空间,这里引入了循环队列,本质上也是顺序存储结构。

链式存储结构:可以不需要事先知道队列的大小,支持动态和释放空间,但是插入和删除操作比较耗时,也称链队列。

建议:当事先基本上确定队列的大小,且插入和删除操作比较频繁时,优先考虑循环队列。。

关于顺序队列还有两句要说的:

顺序队列可以移动数据,亦可以移动头指针

第一种就是这样:这样的话一旦数据过于复杂,就需要大量挪动数据:

 

 下来我们来看看第二种:也就是挪动队头

 

也就是这样,但是你会发现这样如果再插入数据,就会造成“假溢出的现象”。

 

循环队列其实和顺序队列差不多,就是一个环状的队列:

 

 

下面就是循环队列和链式队列的实现:

这是将声明和定义都放在了头文件里面:

#pragma once
#define QUEUE_H
#include<cassert>
#include <iostream>
using namespace std;
template<typename T>
class Queue
{
public:
	Queue(int maxsize = 10);
	Queue(const Queue<T>&x);
	Queue<T>&operator = (const Queue<T>&x);
	~Queue();
public:
	bool Empty()const;
	bool IsFull()const;
	int Size()const;
	void Push(const T&data);
	void Pop();
	T& front()
	{
		if (Empty())
			cerr << "Error,Queue is Empty";
		return array[_front];
	}
	T  front()const
	{
		if (Empty())
			cerr << "Error,Queue is Empty";
		return array[_front];
	}
	T& back()
	{
		if (Empty())
			cerr << "Error,Queue is Empty";
		return array[_rear - 1];
	}
	T  back()const
	{
			if (Empty())
				cerr << "Error,Queue is Empty";
			return array[_rear - 1];
	}



private:
	T* array;
	int _front;
	int _rear;
	int _capacity;
};

#include"Queue.h"

template<typename T>
Queue<T>::Queue(int maxsize)
	:_front(0)
	, _rear(0)
	, _capacity(maxsize)
{
	array = new T[maxsize];
	assert(array != nullptr);

}
template<typename T>
Queue<T>::Queue(const Queue<T>&x)
	:_front(x._front)
	, _rear(x._rear)
	, _capacity(x._capacity)
{
	array = new T[_capacity];
	for (int i = 0;i != (this->Size());i++)
	{
		array[i] = x.array[i];
	}
}
template<typename T>
Queue<T>&Queue<T>::operator = (const Queue<T>&x)
{
	if (this != x);
	{
		delete[] array;
		_capacity = x.capacity;
		_front = x._front;
		_rear = x._rear;
		array = new T[capacity];
		for (int i = 0;i != (this->Size());i++)
		{
			array[i] = x.array[i];
		}
	}
	return *this;
}

template<typename T>
Queue<T>::~Queue()
{
	delete[] array;
}
template<typename T>
bool Queue<T>::Empty()const
{
	return _front == _rear;
}//判空
template<typename T>
bool Queue<T> ::IsFull()const
{
	return (_rear + 1) % _capacity == _front;
}
template<typename T>
int Queue<T>::Size()const
{
	return (_rear - _front + _capacity) % _capacity;
}
template<typename T>
void Queue<T>::Push(const T&data)
{
	if (!IsFull())
	{
		array[_rear] = data;
		_rear = (_rear + 1) % _capacity;

	}
	else
	{
		T *newarray = new T[2 * _capacity];
		for (int i = 0;i != 2 * _capacity&&this->Empty();i++)
		{
			newarray[i] = this->front();
			this->Pop();
		}
		delete[] array;
		array = newarray;
		_front = 0;
		array[_rear] = data;
		_rear = this->_rear + 1;
		_capacity = 2 * _capacity;
	}
}
template<typename T>
void Queue<T>::Pop()
{
	if (!Empty())
	{
		_front = (_front + 1) % _capacity;
	}
	else
		cout << "Queue is Empty" << endl;
}

下面就是测试代码:

#include<iostream>
#include"Queue.h"
using namespace std;

int main()
{
	Queue<int> q(10); //声明队列
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		q.Push(i + 1);
	while (!q.Empty())
	{
		cout << q.front() << " ";
		q.Pop();
		if (!q.Empty()) //此处需要判断此时队列是否为空
		{
			q.Push(q.front());
			q.Pop();
		}
	}
	cout << endl;
	return 0;
}

之后再来实现一下链式队列:

链式队列和链表其实差不多,就是只能实现尾插

这个是头文件(定义和声明)

#pragma once
#include<iostream>
using namespace std;


template <typename T>
class LinkQueue
{
public:
	LinkQueue();
	~LinkQueue();
	bool Empty()const;
	int Size()const;
	void Clear();
	void Push(const T& node);
	void Pop();
	T& front();
	T front()const;
private:
	class QueueNode
	{
	public:
		T _data;
		QueueNode *_next;
		QueueNode(const T& Newdata, QueueNode* nextnode = nullptr)
			:_data(Newdata)
			, _next(nextnode)
		{}
	};
	QueueNode * _front;
	QueueNode* _rear;
	int count;


};
template<typename T>
LinkQueue<T>::LinkQueue()
	:_front(nullptr)
	, _rear(nullptr)
	, count(0)
{}
template<typename T>
LinkQueue<T>::~LinkQueue()
{
	Clear();
}
template<typename T>
void LinkQueue<T>::Push(const T &node)
{
	if (_front == nullptr)
	{
		_front = _rear = new QueueNode(node);
	}
	else {
		QueueNode *newqueuenode = new QueueNode(node);
		_rear->_next = newqueuenode;
		_rear = newqueuenode;

	}
	count++;
}

template<typename T>
int LinkQueue<T>::Size()const
{
	return count;
}


template<typename T>
bool LinkQueue<T>::Empty()const
{
	return _front == nullptr;
}
template<typename T>
void LinkQueue<T>::Clear()
{
	while (_front)
	{
		QueueNode * frontofqueue = _front;
		_front = _front->_next;
		delete frontofqueue;
	}
	count = 0;
}
template<typename T>
void LinkQueue<T>::Pop()
{
	if (Empty())
	{
		cerr << "LinkQueue is empty" << endl;

	}
	QueueNode *frontofqueue = _front;
	_front = _front->_next;
	delete frontofqueue;
	count--;
}
template<typename T>
T& LinkQueue<T>::front()
{
	if (Empty())
	{
		cerr << "LinkQueue is empty" << endl;

	}
	return _front->_data;
}
template<typename T>
T LinkQueue<T>::front()const
{
	if (Empty())
	{
		cerr << "LinkQueue is empty" << endl;

	}
	return _front->_data;
}

 下面是测试代码:

#include<iostream>
#include"LinkQueue.h"
using namespace std;

int main()
{
	LinkQueue<int> q; //声明队列
	int n;
	cin >> n;
	for (int i = 0; i<n; i++)
		q.Push(i + 1);
	while (!q.Empty())
	{
		cout << q.front() << " ";
		q.Pop();
		if (!q.Empty()) //此处需要判断此时队列是否为空
		{
			q.Push(q.front());
			q.Pop();
		}
	}
	cout << endl;
	return 0;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值