C++數據結構:普通隊列與循環隊列

什麼是隊列?

       隊列是一種特殊的線性表,它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作。隊列中的數據元素遵循“先進先出”(First In First Out)的原則,簡稱FIFO結構。

 

隊列分類

      普通隊列與循環隊列,普通隊列可以看做是一列數據,環形隊列可以看做是一個圓,當普通隊列的數據索引可以循環設置時,普通隊列就成了循環隊列。這兩種都可以用數組來實現。

 

循環隊列的C++實現

       下面說明用數組實現循環隊列的方法

     (1)隊頭和隊尾都是0位置,從隊尾插入,隊頭取數據。

     (2)插入數據:每次插入數據時,先判斷隊列是否是滿的。在隊列未滿時,從隊尾插入數據,隊尾移向下一個位置。在隊列滿了時,如果要再插入數據,此時就得把隊頭數據彈出,隊頭指向下一個位置,再從隊尾插入。

     (3)取數據,從隊頭取。

 

  示例代碼:

  頭文件

/*

環形隊列

用數組模擬環形隊列的實現

*/

#pragma once

class CircularQueue
{
public:
	CircularQueue(int capcity);
	~CircularQueue();

	int getQueueLength() const;
	bool isEmpty();
	bool isFull();
	void Clear();
	void Push(int data);  //插入新元素,隊尾插
	int Pop();    //彈出首元素
	void Print();

private:
	int *m_pCirQueue;  //存放隊列數據的數組容器
	int m_iCapacity;   //隊列容量
	int m_iLength;     //隊列長度
	int m_iHead;       //隊列頭索引
	int m_iTail;       //隊列尾部索引

};

cpp文件

#include "CircularQueue.h"
#include <iostream>

using namespace std;

CircularQueue::CircularQueue(int capcity)
{
	m_iCapacity = capcity;
	m_iHead = 0;
	m_iTail = 0;
	m_iLength = 0;
	m_pCirQueue = new int[m_iCapacity];
}

CircularQueue::~CircularQueue()
{
	delete[] m_pCirQueue;
}

int CircularQueue::getQueueLength() const
{
	return m_iLength;
}

bool CircularQueue::isEmpty()
{
	if (m_iLength > 0)
	{
		return false;
	}

	return true;
}

bool CircularQueue::isFull()
{
	if (m_iLength == m_iCapacity)
	{
		return true;
	}

	return false;
}

void CircularQueue::Clear()
{
	m_iLength = 0;
	m_iHead = 0;
	m_iTail = 0;
}

void CircularQueue::Push(int data)
{
	if (isFull())
	{
		Pop();
	}

	m_pCirQueue[m_iTail] = data;
	m_iTail++;  //尾部指向下一個位置

	m_iTail = m_iTail % m_iCapacity;
	m_iLength++;
}

int CircularQueue::Pop()
{
	if (isEmpty())
	{
		return false;
	}

	int pop = m_pCirQueue[m_iHead];
	m_iHead++;
	m_iHead = m_iHead % m_iCapacity;
	m_iLength--;
	return pop;
}

//遍歷循環隊列
void CircularQueue::Print()
{
	for (int i = m_iHead; i < m_iHead + m_iLength; i++)
	{
		cout << m_pCirQueue[i % m_iCapacity] << " ";
	}

	cout << endl;
}

main.cpp測試循環隊列的功能

#include <iostream>
#include "CircularQueue.h"

using namespace std;

int main()
{
	CircularQueue *pQueue = new CircularQueue(4);

	pQueue->Push(2);
	pQueue->Push(4);
	pQueue->Push(6);
	pQueue->Push(8);
	pQueue->Push(9);
	
	cout << "遍歷隊列" << endl;
	pQueue->Print();

	pQueue->Pop();
	cout << "遍歷隊列" << endl;
	pQueue->Print();

	system("pause");
	return 0;
}

運行結果:

 

模板隊列的實現

       上面是用的int數組作爲隊列容器,我們可以用模板對其改造,代碼如下,新建一個模板隊列類TCircularQueue, 代碼如下:

       TCircularQueue.h

#pragma once

template<typename T>
class TCircularQueue
{
public:
	TCircularQueue(int capacity = 10);
	~TCircularQueue();

	int getQueueLength() const;
	bool isEmpty();
	bool isFull();
	void Clear();
	void Push(T data);  //插入新元素,隊尾插
	T Pop();    //彈出首元素
	T* Print();

private:
	T *m_pCirQueue;  //存放隊列數據的數組容器
	int m_iCapacity;   //隊列容量
	int m_iLength;     //隊列長度
	int m_iHead;       //隊列頭索引
	int m_iTail;       //隊列尾部索引
};

template<typename T>
TCircularQueue<T>::TCircularQueue(int capacity)
{
	m_iCapacity = capacity;
	m_iHead = 0;
	m_iTail = 0;
	m_iLength = 0;
	m_pCirQueue = new T[m_iCapacity];
}

template<typename T>
TCircularQueue<T>::~TCircularQueue()
{
	delete[] m_pCirQueue;
}

template<typename T>
int TCircularQueue<T>::getQueueLength() const
{
	return m_iLength;
}

template<typename T>
bool TCircularQueue<T>::isEmpty()
{
	if (m_iLength > 0)
	{
		return false;
	}

	return true;
}

template<typename T>
bool TCircularQueue<T>::isFull()
{
	if (m_iLength == m_iCapacity)
	{
		return true;
	}

	return false;
}

template<typename T>
void TCircularQueue<T>::Clear()
{
	m_iLength = 0;
	m_iHead = 0;
	m_iTail = 0;
}

template<typename T>
void TCircularQueue<T>::Push(T data)
{
	if (isFull())
	{
		Pop();
	}

	m_pCirQueue[m_iTail] = data;
	m_iTail++;  //尾部指向下一個位置

	m_iTail = m_iTail % m_iCapacity;
	m_iLength++;
}

template<typename T>
T TCircularQueue<T>::Pop()
{
	T pop;

	if (isEmpty())
	{
		return pop;
	}

	pop = m_pCirQueue[m_iHead];
	m_iHead++;
	m_iHead = m_iHead % m_iCapacity;
	m_iLength--;
	return pop;
}

//遍歷循環隊列
template<typename T>
T* TCircularQueue<T>::Print()
{
	T *p = NULL;
	if (m_iLength > 0)
	{
		p = new T[m_iLength];

		for (int i = m_iHead, j = 0; i < m_iHead + m_iLength, j < m_iLength; i++, j++)
		{
			//cout << m_pCirQueue[i % m_iCapacity] << " ";
			p[j] = m_pCirQueue[i % m_iCapacity];
		}
	}

	return p;
}


     在新建一個Student類作爲模板數據

     .h

#pragma once

#include<iostream>
#include<string>

using namespace std;

class Student
{
public:
	Student(string name = "", int age = 10);
	
	void Print();

private:
	string m_name;
	int    m_iAge;
};

    .cpp

#include "Student.h"

Student::Student(string name, int age)
{
	m_name = name;
	m_iAge = age;
}

void Student::Print()
{
	cout << "name = " << m_name << " age = " << m_iAge << endl;
}

    測試代碼:

#include <iostream>
#include "TCircularQueue.h"
#include "Student.h"

using namespace std;

int main()
{
	TCircularQueue<Student> *pQueue = new TCircularQueue<Student>(4);

	Student st1("魯班", 13);
	Student st2("後裔", 400);
	Student st3("安其拉", 14);
	Student st4("甄姬", 25);
	Student st5("妲己", 19);
	Student st6("亞瑟", 78);

	pQueue->Push(st1);
	pQueue->Push(st2);
	pQueue->Push(st3);
	pQueue->Push(st4);
	pQueue->Push(st5);
	pQueue->Push(st6);
	
	int leng = pQueue->getQueueLength();
	cout << "leng = " << leng << endl;

	Student *p = new Student[leng];
	cout << "遍歷隊列" << endl;
	p = pQueue->Print();
	for (int i = 0; i < leng; i++)
	{
		p[i].Print();
	}

	delete pQueue;

	system("pause");
	return 0;
}

      運行結果

      隊列在開發中應用的很多,比如線程池,音視頻同步等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章