图解数据结构(3)——队

本文深入探讨了队列的概念、特点及其在缓冲区管理和树的广度优先遍历中的应用。通过实例展示了如何使用队列进行树的广度优先遍历,并提供了相应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

五、队(Queue)

前一篇讲了栈(Stack),队和栈其实只有一个差别,栈是先进后出,队是先进先出,如图:

从图中可以看出,队有两个常用的方法,Enqueue和Dequeue,顾名思义,就是进队和出队了。队和栈一样,既可以用数组实现,也可以用链表实现,我还是偏向于用数组,我的实现示意图如下:

队有啥用呢?一个最常用的用途就是“buffer”,即缓冲区,比如有一批从网络来的数据,处理需要挺长的时间,而数据抵达的间隔并不均匀,有时快,有时慢,先来的先处理,后来的后处理,于是你创建了一个队,用来缓存这些数据,出队一笔,处理一笔,直到队列为空。当然队的作用远不止于此,下面的例子也是一个很经典的例子,希望读者能举一反三。

例子:使用队对树进行广度优先遍历。

广度优先区别于深度优先,即优先遍历最靠近根节点的各个节点:

我们的算法是:
1,根节点入队
2,出队一个节点,算一次遍历,直到队列为空
3,将刚出队的节点的子节点入队
4,转到2

队列的状况如下图:


树的遍历一般习惯使用递归,理论上所有的递归都可以转变为迭代,如何实现这个转变?队就是其中一种有效的办法,OK,下面我给出上述例题的代码以及注释。

//Not grace code but enough for demo. ^_^
#include "stdio.h"

// The Node
//////////////////////////////////////////////////////////////////////////
struct Node
{
Node(
char cChar, int iSubNodeNum=0);
~Node();

char m_cChar;

int m_iSubNodeNum;
Node
** m_arrNodePointer; //Pointers to the sub-node.
};

Node::Node(
char cChar, int iSubNodeNum)
{
m_cChar
= cChar;

m_iSubNodeNum
= iSubNodeNum;

if(iSubNodeNum!=0)
m_arrNodePointer
=new Node*[iSubNodeNum];
else
m_arrNodePointer
= NULL;
}

Node::
~Node()
{
if(m_arrNodePointer!=NULL)
delete[] m_arrNodePointer;
}

// The Queue
//////////////////////////////////////////////////////////////////////////
class Queue
{
public:
Queue(
int iAmount=10);
~Queue();

//return 0 means failed, return 1 means succeeded.
int Enqueue(Node* node);
int Dequeue(Node*& node);
private:
int m_iAmount;
int m_iCount;
Node
** m_ppFixed; //The pointer array to implement the queue.

int m_iHead;
int m_iTail;
};

Queue::Queue(
int iAmount)
{
m_iCount
=0;
m_iAmount
= iAmount;
m_ppFixed
=new Node*[iAmount];

m_iHead
=0;
m_iTail
= iAmount-1;
}

Queue::
~Queue()
{
delete[] m_ppFixed;
}

int Queue::Enqueue(Node* node)
{
if(m_iCount<m_iAmount)
{
++m_iTail;
if(m_iTail > m_iAmount-1)
m_iTail
=0;
m_ppFixed[m_iTail]
= node;
++m_iCount;
return1;
}
else
return0;
}

int Queue::Dequeue(Node*& node)
{
if(m_iCount>0)
{
node
= m_ppFixed[m_iHead];
++m_iHead;
if(m_iHead > m_iAmount-1)
m_iHead
=0;
--m_iCount;
return1;
}
else
return0;
}

// Main
//////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
//Construct the tree.
Node nA('A', 3);
Node nB(
'B', 2);
Node nC(
'C');
Node nD(
'D', 3);
Node nE(
'E');
Node nF(
'F', 2);
Node nG(
'G');
Node nH(
'H', 1);
Node nI(
'I');
Node nJ(
'J');
Node nK(
'K');
Node nL(
'L');
nA.m_arrNodePointer[
0] =&nB;
nA.m_arrNodePointer[
1] =&nC;
nA.m_arrNodePointer[
2] =&nD;
nB.m_arrNodePointer[
0] =&nE;
nB.m_arrNodePointer[
1] =&nF;
nD.m_arrNodePointer[
0] =&nG;
nD.m_arrNodePointer[
1] =&nH;
nD.m_arrNodePointer[
2] =&nI;
nF.m_arrNodePointer[
0] =&nJ;
nF.m_arrNodePointer[
1] =&nK;
nH.m_arrNodePointer[
0] =&nL;

Queue que;
que.Enqueue(
&nA);

Node
*pNode;
while (que.Dequeue(pNode)==1)
{
printf(
"%c ", pNode->m_cChar);
int i;
for(i=0; i<pNode->m_iSubNodeNum; i++)
{
que.Enqueue(pNode
->m_arrNodePointer[i]);
}
}

return0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值