摘要:
it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结构。
此系列专注讲解数据结构数组、链表、队列、栈、树、哈希表、图,通过介绍概念以及提及一些可能适用的场景,并以C++代码简易实现,多方面认识数据结构,最后为避免重复造轮子会浅提对应的STL容器。本文介绍的是队Queue。
(开发环境:VScode,C++17)
关键词
: C++,数据结构,队列,Queue
声明:
本文作者原创,转载请附上文章出处与本文链接。
文章目录
- 摘要:
- 正文:
- 介绍:
- 特性:
- 应用:
- 代码实现:
- 对应STL:
- 推荐阅读
正文:
介绍:
队列(Queue)是一种常见的数据结构,它遵循先入先出(FIFO,First In First Out)的原则。队列中的元素按照它们进入队列的顺序排列,并且只有队首的元素可以被删除,队尾的元素可以被添加。
队列也有两种存储表示方法:顺序存储(用数组实现)和链式存储(用链表实现),顺序存储常见的就是环形队列,初始化时必须指定队列容量大小;普通队列则基于链表。
特性:
-
先进先出:队列的基本操作是遵循FIFO(先进先出)原则的。这意味着最早添加到队列中的元素将是最早被移除的。这种特性使得队列在处理需要按顺序处理的元素时非常有用,比如任务调度、打印作业等。
-
受限的访问:队列只允许在两端进行操作。在队列的一端(称为“队尾”或“后端”)添加元素,而在另一端(称为“队头”或“前端”)移除元素。这种特性确保了队列中的元素按照它们被添加的顺序进行处理。
应用:
队列在多种场景中都有应用,包括:
- 任务调度:在计算机系统中,多个任务可能同时请求CPU资源。使用队列可以确保任务按照它们到达的顺序得到处理。
- 打印机作业队列:当一个用户提交一个打印作业时,它会被添加到打印队列中。打印机按照作业进入队列的顺序打印它们。
- 网络数据包处理:在网络通信中,接收到的数据包需要按照它们到达的顺序进行处理。队列可以帮助管理这些数据包,确保它们按照正确的顺序被处理。
- 图形界面事件处理:在图形用户界面(GUI)中,用户事件(如鼠标点击或键盘输入)被添加到事件队列中。事件处理程序按照事件进入队列的顺序处理它们。
代码实现:
#cqueue.h
#ifndef CQUEUE_H
#define CQUEUE_H
#include <iostream>
using namespace std;
// 队链节点
template<class T>
class CQueueNode
{
public:
CQueueNode(T t) :data(t), next(NULL) {}
~CQueueNode() { next = NULL; }
CQueueNode(const CQueueNode& node)
{
if (this == &node){
return;
}
*this = node;
}
CQueueNode& operator=(const CQueueNode& node)
{
if (this == &node){
return *this;
}
this->data = node.data;
this->next = node.next;
return *this;
}
public:
T data;
CQueueNode *next;
};
// 普通队列实现,基于链表
template<class T>
class CQueue
{
public:
CQueue() :head(NULL), tail(NULL), node(NULL), m_iSize(0) {}
~CQueue()
{
delete head;head = NULL;
delete tail;tail = NULL;
delete node;node = NULL;
}
int size(); // 获取队内成员个数
bool empty(); // 判断是否为空队列
void push(T t); // 队尾入队
T pop(); // 队首出队
T front(); // 返回队首
T back(); // 返回队尾
void traverse(); // 打印整个队列
private:
CQueueNode<T>* head;
CQueueNode<T>* tail;
CQueueNode<T>* node;
int m_iSize;
};
template<class T>
int CQueue<T>::size()
{
return m_iSize;
}
template<class T>
bool CQueue<T>::empty()
{
return 0 == m_iSize;
}
template<class T>
void CQueue<T>::push(T t)
{
node = new CQueueNode<T>(t);
if (head == NULL){
head = tail = node;
}
else{
tail->next = node;
tail = node;
}
m_iSize++;
}
template<class T>
T CQueue<T>::pop()
{
if (empty()){
throw "empty queue.";
}
node = head;
head = head->next;
m_iSize--;
return node->data;
}
template<class T>
T CQueue<T>::front()
{
if (empty()){
throw "empty queue.";
}
return head->data;
}
template<class T>
T CQueue<T>::back()
{
if (empty()){
throw "empty queue.";
}
return tail->data;
}
template<class T>
void CQueue<T>::traverse()
{
CQueueNode<T> *node = head;
while (node != NULL){
cout << node->data << " ";
node = node->next;
}
cout << endl;
}
#endif // !CQUEUE_H
#cqueue.cpp
#include "cqueue.h"
using namespace std;
int main(int argc, char**argv)
{
CQueue<char> queue;
queue.push('h');
queue.push('e');
queue.push('l');
queue.push('l');
queue.push('o');
queue.push(' ');
queue.push('w');
queue.push('o');
queue.push('r');
queue.push('l');
queue.push('d');
queue.traverse();
cout << queue.front() << endl;
cout << queue.back() << endl;
char c = queue.pop();
cout << c << endl;
queue.traverse();
return 0;
}
对应STL:
-
queue:
普通队列。其原理是先进先出(FIFO),只有队头和队尾可以被访问,故不可有遍历行为,默认也为deque双端队列
-
deque:
双端队列。支持头插、删,尾插、删,随机访问较vector容器来说慢,但对于首尾的数据操作比较方便
推荐阅读
C/C++专栏:https://blog.csdn.net/weixin_45068267/category_12268204.html
(内含其它数据结构及对应STL容器使用)