什麼是隊列?
隊列是一種特殊的線性表,它只允許在表的前端(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;
}
運行結果
隊列在開發中應用的很多,比如線程池,音視頻同步等。