数据结构与算法——队列

1 概述

  • 先进先出(FIFO)的线性表
  • 队尾:插入元素;队首:删除元素
    在这里插入图片描述
  • 抽象数据类型:queue ADT
    在这里插入图片描述
    在这里插入图片描述
    C++代码实现:
template<class T>
class queue
{
public:
	virtual ~queue() {}
	virtual bool empty() const = 0;
	// return true iff queue is empty
	virtual int size() const = 0;
	// return number of elements in queue
	virtual T& front() = 0;
	// return reference to the front element
	virtual T& back() = 0;
	// return reference to the back element
	virtual void pop() = 0;
	// remove the front element
	virtual void push(const T& theElement) = 0;
	// add theElement at the back of the queue
};

2 数组描述

2.1 数组和队列的映射

  • 方案一:采用公式 l o c a t i o n ( i ) = i location(i)=i location(i)=i
    queue[i]为队列中第i个元素,arrayLength是队列的长度,queueFront和queueBack分别为队首和队尾元素位置,则有: q u e u e F r o n t = 0 queueFront=0 queueFront=0 q u e u e B a c k = a r r a y L e n g t h − 1 queueBack=arrayLength-1 queueBack=arrayLength1
    特别地,当队列为空时: q u e u e B a c k = − 1 queueBack=-1 queueBack=1
    在这里插入图片描述
    插入元素:queueBack++,queue[queueBack]=theElement。
    删除元素:queue[1: queueBack]整体左移一个位置(时间复杂度线性
  • 方案二:采用公式 l o c a t i o n ( i ) = l o c a t i o n ( 队 首 元 素 ) + i location(i)=location(队首元素)+i location(i)=location()+i
    在这里插入图片描述
    按照上述公式,则有: q u e u e F r o n t = l o c a t i o n ( 队 首 元 素 ) queueFront=location(队首元素) queueFront=location() q u e u e B a c k = l o c a t i o n ( 队 尾 元 素 ) queueBack=location(队尾元素) queueBack=location()
    特别地,当队列为空时: q u e u e B a c k &lt; q u e u e F r o n t queueBack&lt;queueFront queueBack<queueFront
    在最坏的情况下想要插入元素,仍然不能避免队列整体向左平移,从而降低了插入效率
  • 方案三:采用公式 l o c a t i o n ( i ) = ( l o c a t i o n ( 队 首 元 素 ) + i ) % a r r a y L e n g t h location(i)=(location(队首元素)+i)\%arrayLength location(i)=(location()+i)%arrayLength
    将数组视为一个环,arrayLength-1的下一个是0,0的前一个是arrayLength-1。
    在这里插入图片描述
    在这种情况下,当且仅当 q u e u e F r o n t = q u e u e B a c k queueFront=queueBack queueFront=queueBack时,队列为空,然而queue元素个数等于数组长度时, q u e u e F r o n t = q u e u e B a c k queueFront=queueBack queueFront=queueBack也成立,解决办法是:队列不能插满,队列元素个数最多是arrayLength-1
    2.2 C++语言实现
    arrayQueue类声明:
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()
	{// return front element
		if (theFront == theBack)
			throw queueEmpty();
		return queue[(theFront + 1) % arrayLength];
	}
	T& back()
	{// return theBack element
		if (theFront == theBack)
			throw queueEmpty();
		return queue[theBack];
	}
	void pop()
	{// remove theFront element
		if (theFront == theBack)
			throw queueEmpty();
		theFront = (theFront + 1) % arrayLength;
		queue[theFront].~T();  // destructor for T
	}
	void push(const T & theElement);
private:
	int theFront;       // 1 counterclockwise from theFront element
	int theBack;        // position of theBack element
	int arrayLength;    // queue capacity
	T * queue;          // element array
};

push方法实现:

template<class T>
void arrayQueue<T>::push(const T & theElement)
{// Add theElement to queue.

   // increase array length if necessary
	if ((theBack + 1) % arrayLength == theFront)
	{// double array length
	   // allocate a new array
		T* newQueue = new T[2 * arrayLength];

		// copy elements into new array
		int start = (theFront + 1) % arrayLength;
		if (start < 2)
			// no wrap around
			copy(queue + start, queue + start + arrayLength - 1, newQueue);
		else
		{  // queue wraps around
			copy(queue + start, queue + arrayLength, newQueue);
			copy(queue, queue + theBack + 1, newQueue + arrayLength - start);
		}

		// switch to newQueue and set theFront and theBack
		theFront = 2 * arrayLength - 1;
		theBack = arrayLength - 2;   // queue size arrayLength - 1
		arrayLength *= 2;
		queue = newQueue;
	}

	// put theElement at the theBack of the queue
	theBack = (theBack + 1) % arrayLength;
	queue[theBack] = theElement;
}

3 链表描述

从头到尾和从尾到头
在这里插入图片描述
对比:插入操作
在这里插入图片描述
插入操作均适用。
对比:删除操作
在这里插入图片描述
从头至尾的链接方向更适合删除操作。
给出从头至尾链接的插入和删除操作实现代码:

template<class T>
void linkedQueue<T>::pop()
{// Delete front element.
   if (queueFront == NULL)
   	throw queueEmpty();

   chainNode<T> * nextNode = queueFront->next;
   delete queueFront;
   queueFront = nextNode;
   queueSize--;
}


template<class T>
void linkedQueue<T>::push(const T & theElement)
{// Add theElement to back of queue.

  // create node for new element
   chainNode<T>* newNode = new chainNode<T>(theElement, NULL);

   // add new node to back of queue
   if (queueSize == 0)
   	queueFront = newNode;       // queue empty
   else
   	queueBack->next = newNode;  // queue not empty
   queueBack = newNode;

   queueSize++;
}

4 应用

列车车厢重排
电路布线
图元识别
工厂仿真

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值