数据结构学习笔记(四)队列及其C++实现

一、队列

       队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。我们把允许插入的一端称为队尾,允许删除的一端称为队头。队列是一种先进先出(FIFO)的线性表。

     比如人们在买东西排队的时候,整个队伍可以看做一个队列,我们当然不希望有人加沙了。在服务器的应用中,也要一个队列来选择相应服务的优先级。


       队列的基本操作和栈类似,有创建空队列,添加元素,删除元素,返回队列大小,返回队头和队尾元素等等。在C++标准库中,也有队列的定义。

       队列也有顺序存储结构和链式存储结构,其C++实现如下:

二、队列的抽象基类

//队列的抽象类
#pragma once 
#include<iostream>
using namespace std;

template<class T>
class queue
{
public:
	~queue() {}
	virtual bool empty() const = 0;//判断是否为空
	virtual int size() const = 0;//返回队列的大小
	virtual T& front() = 0;//返回头元素的引用
	virtual T& back() = 0;//返回尾元素的引用
	virtual void pop() = 0;//删除首元素
	virtual void push(const T& theElement) = 0;//添加队列元素
	virtual void output(ostream& out) const = 0;//输出
};


三、队列的数组表示

#pragma once
#include<iostream>
#include <algorithm>
#include<string>
#include<iterator>
#include"queue.h"
using namespace std;

//使用环形数组实现队列,Front指向第一个元素的前一个位置,Back指向最后一个元素

template<class T>
class arrayQueue : public queue<T>
{
public:
	arrayQueue(int initialCapacity = 10);
	~arrayQueue() { delete[] queue; }
	bool empty() const { return theFront == theBack; }
	int size() const
	{
		return (theBack - theFront + arrayLength) % arrayLength;
	}
	T& front()
	{//返回首元素
		if (theFront == theBack)
		{
			cerr << "Queue is empty";
			exit(0);
		}

		return queue[(theFront + 1) % arrayLength];
	}
	T& back()
	{// 返回尾元素
		if (theFront == theBack)
		{
			cerr << "Queue is empty";
			exit(0);
		}
		return queue[theBack];
	}
	void pop()
	{// 弹出队列首元素
		if (theFront == theBack)
		{
			cerr << "Queue is empty";
			exit(0);
		}
		theFront = (theFront + 1) % arrayLength;
		queue[theFront].~T();  //析构T
	}
	void push(const T& theElement);
	void output(ostream& out) const;

private:
	int theFront;       // 指向队列首元素的前一个
	int theBack;        // 指向队列尾元素
	int arrayLength;    // 队里容量
	T *queue;           //队列指针
};

template<class T>
arrayQueue<T>::arrayQueue(int initialCapacity)
{// 构造函数
	if (initialCapacity < 1)
	{
		cerr << "Initial Capacity Must be >0";
		exit(0);
	}
	arrayLength = initialCapacity;
	queue = new T[arrayLength];
	theFront = 0;
	theBack = 0;
}

template<class T>
void arrayQueue<T>::push(const T& theElement)
{//添加元素.

	// 如果队列满,增加队列容量
	if ((theBack + 1) % arrayLength == theFront)
	{// 双倍长度
		// 创建新数组
		T* newQueue = new T[2 * arrayLength];

		//赋值元素
		int start = (theFront + 1) % arrayLength;
		if (start < 2)
			// 没有形成环,直接从Front到Back赋值
			copy(queue + start, queue + start + arrayLength - 1, newQueue);
		else
		{  // 队列形成环,先从Front到数组的末尾进行复制,然后在数组开始到Back进行复制
			copy(queue + start, queue + arrayLength, newQueue);
			copy(queue, queue + theBack + 1, newQueue + arrayLength - start);
		}

		// 设置新队列的首尾位置
		theFront = 2 * arrayLength - 1;
		theBack = arrayLength - 2;   // 队列长度 arrayLength - 1
		arrayLength *= 2;
		queue = newQueue;
	}

	// 添加元素操作
	theBack = (theBack + 1) % arrayLength;
	queue[theBack] = theElement;
}


//输出操作  
template<class T>
void arrayQueue<T>::output(ostream& out) const
{
	T* newQueue = new T[arrayLength+5];
	int start = (theFront + 1) % arrayLength;
	if (start < 2)//没有形成环
		copy(queue + start, queue + arrayLength, newQueue);
	else
	{//队列形成环
		copy(queue + start, queue + arrayLength, newQueue);
		copy(queue, queue + theBack + 1, newQueue + arrayLength - start);
	}
	copy(newQueue, newQueue + size(), ostream_iterator<T>(out, " "));
}
template<class T>
ostream& operator<<(ostream& out, const arrayQueue<T>& x)
{
	x.output(out);
	return out;
}



测试代码:

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

void main()
{
	arrayQueue<int> que(4);
	cout << que.empty() << endl;
	for (int i = 0; i < 8; i++)
	{
		que.push(i);
	}
	cout << que << endl;
	cout << que.front() << " " << que.back() << endl; 
	que.pop();
	que.pop();
	cout << que << endl; 
	cout << que.front() << " " << que.back() << endl;
}


四、队列的链表描述

#pragma once
#include<iostream>
#include"queue.h"
using namespace std;

template<class T>
struct linkedNode
{
	T element;//数据域
	linkedNode<T>* next;//指针域

	linkedNode(){}
	linkedNode(const T& element){ this->element = element; }
	linkedNode(const T& element, linkedNode<T>* next) { this->element = element; this->next = next; }
};

//队列的链表表示
template<class T>
class linkedQueue :public queue<T>
{
public:
	//构造函数和析构函数
	linkedQueue(int initialCapacity = 10)
	{
		queueFront = queueBack = NULL;
		queueSize = 0;
	}
	~linkedQueue()
	{
		while (queueFront->next != NULL)
		{
			linkedNode<T>* nextNode = queueFront->next;//新的节点指示下一个节点
			delete queueFront;//删除当前节点
			queueFront = nextNode;//将下一个节点赋给当前结点
		}
	}

	//抽象数据类型的实现
	bool empty() const //判断是否为空
	{
		return queueSize == 0;
	}
	int size() const //返回队列的大小
	{
		return queueSize;
	}
	T& front() //返回头元素的引用
	{
		if (queueSize==0)
		{
			cerr << "The Queue is empty";
			exit(0);
		}
		return queueFront->element;
	}
	T& back() //返回尾元素的引用
	{
		if (queueSize == 0)
		{
			cerr << "The Queue is empty";
			exit(0);
		}
		return queueBack->element;
	}
	void pop();//删除首元素
	void push(const T& theElement);//添加队列元素
	void output(ostream& out) const ;//输出

private:
	linkedNode<T>* queueFront;//指向队列首元素
	linkedNode<T>* queueBack;//指向队列尾元素
	int queueSize;
};

//插入操作到队尾
template<class T>
void linkedQueue<T>::push(const T& theElement)
{
	linkedNode<T>*  newNode = new linkedNode<T>(theElement, NULL);//分配新的空间
	if (queueSize==0)
	{//空队列插入到第一位
		queueFront = newNode;
	}
	else
	{//插入到尾部
		queueBack->next = newNode;
	}
	queueBack = newNode;
	queueSize++;
}

//删除队列首元素
template<class T>
void linkedQueue<T>::pop()
{
	if (queueSize == 0)
	{
		cerr << "The Queue is empty";
		exit(0);
	}
	linkedNode<T>* nextNode = queueFront->next;
	delete queueFront;
	queueFront = nextNode;
	queueSize--;
}

//输出操作
template<class T>
void linkedQueue<T>::output(ostream& out) const //吧链表放入到输出流
{
	for (linkedNode<T>* currentNode = queueFront; currentNode != NULL; currentNode = currentNode->next)
		out << currentNode->element << " ";
}
template<class T>
ostream& operator<<(ostream& out, const linkedQueue<T>& x)
{
	x.output(out);
	return out;
}


测试代码:

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

void main()
{
	linkedQueue<int> que(4);
	//que.pop();
	cout << que.empty() << endl;
	for (int i = 0; i < 17; i++)
	{
		que.push(i);
	}
	cout << que << endl;
	cout << que.front() << " " << que.back() << endl; 
	que.pop();
	que.pop();
	cout << que << endl; 
	cout << que.front() << " " << que.back() << endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值