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

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

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

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

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

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

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

队列的状况如下图:

树的遍历一般习惯使用递归,理论上所有的递归都可以转变为迭代,如何实现这个转变?队就是其中一种有效的办法,OK,下面我给出上述例题的代码以及注释。
  1. //Not grace code but enough for demo. ^_^  
  2. #include "stdio.h"  
  3.   
  4. // The Node  
  5. //////////////////////////////////////////////////////////////////////////  
  6. struct Node  
  7. {  
  8.     Node(char cChar, int iSubNodeNum=0);  
  9.     ~Node();  
  10.   
  11.     char m_cChar;  
  12.   
  13.     int m_iSubNodeNum;  
  14.     Node** m_arrNodePointer; //Pointers to the sub-node.  
  15. };  
  16.   
  17. Node::Node(char cChar, int iSubNodeNum)  
  18. {  
  19.     m_cChar = cChar;  
  20.   
  21.     m_iSubNodeNum = iSubNodeNum;  
  22.   
  23.     if(iSubNodeNum!=0)  
  24.         m_arrNodePointer = new Node*[iSubNodeNum];  
  25.     else  
  26.         m_arrNodePointer = NULL;  
  27. }  
  28.   
  29. Node::~Node()  
  30. {  
  31.     if(m_arrNodePointer!=NULL)  
  32.         delete[] m_arrNodePointer;  
  33. }  
  34.   
  35. // The Queue  
  36. //////////////////////////////////////////////////////////////////////////  
  37. class Queue  
  38. {  
  39. public:  
  40.     Queue(int iAmount=10);  
  41.     ~Queue();  
  42.   
  43.     //return 0 means failed, return 1 means succeeded.  
  44.     int Enqueue(Node* node);  
  45.     int Dequeue(Node* & node);  
  46. private:  
  47.     int m_iAmount;  
  48.     int m_iCount;  
  49.     Node** m_ppFixed; //The pointer array to implement the queue.  
  50.   
  51.     int m_iHead;  
  52.     int m_iTail;  
  53. };  
  54.   
  55. Queue::Queue(int iAmount)  
  56. {  
  57.     m_iCount = 0;  
  58.     m_iAmount = iAmount;  
  59.     m_ppFixed = new Node*[iAmount];  
  60.       
  61.     m_iHead = 0;  
  62.     m_iTail = iAmount-1;  
  63. }  
  64.   
  65. Queue::~Queue()  
  66. {  
  67.     delete[] m_ppFixed;  
  68. }  
  69.   
  70. int Queue::Enqueue(Node* node)  
  71. {  
  72.     if(m_iCount<m_iAmount)  
  73.     {  
  74.         ++m_iTail;  
  75.         if(m_iTail > m_iAmount-1)  
  76.             m_iTail = 0;  
  77.         m_ppFixed[m_iTail] = node;  
  78.         ++m_iCount;  
  79.         return 1;  
  80.     }  
  81.     else  
  82.         return 0;  
  83. }  
  84.   
  85. int Queue::Dequeue(Node* & node)  
  86. {  
  87.     if(m_iCount>0)  
  88.     {  
  89.         node = m_ppFixed[m_iHead];  
  90.         ++m_iHead;  
  91.         if(m_iHead > m_iAmount-1)  
  92.             m_iHead = 0;  
  93.         --m_iCount;  
  94.         return 1;  
  95.     }  
  96.     else  
  97.         return 0;  
  98. }  
  99.   
  100. // Main  
  101. //////////////////////////////////////////////////////////////////////////  
  102. int main(int argc, char* argv[])  
  103. {  
  104.     //Construct the tree.  
  105.     Node nA('A', 3);  
  106.     Node nB('B', 2);  
  107.     Node nC('C');  
  108.     Node nD('D', 3);  
  109.     Node nE('E');  
  110.     Node nF('F', 2);  
  111.     Node nG('G');  
  112.     Node nH('H', 1);  
  113.     Node nI('I');  
  114.     Node nJ('J');  
  115.     Node nK('K');  
  116.     Node nL('L');  
  117.     nA.m_arrNodePointer[0] = &nB;  
  118.     nA.m_arrNodePointer[1] = &nC;  
  119.     nA.m_arrNodePointer[2] = &nD;  
  120.     nB.m_arrNodePointer[0] = &nE;  
  121.     nB.m_arrNodePointer[1] = &nF;  
  122.     nD.m_arrNodePointer[0] = &nG;  
  123.     nD.m_arrNodePointer[1] = &nH;  
  124.     nD.m_arrNodePointer[2] = &nI;  
  125.     nF.m_arrNodePointer[0] = &nJ;  
  126.     nF.m_arrNodePointer[1] = &nK;  
  127.     nH.m_arrNodePointer[0] = &nL;  
  128.   
  129.     Queue que;  
  130.     que.Enqueue(&nA);  
  131.       
  132.     Node *pNode;  
  133.     while (que.Dequeue(pNode)==1)   
  134.     {  
  135.         printf("%c ", pNode->m_cChar);  
  136.         int i;  
  137.         for(i=0; i<pNode->m_iSubNodeNum; i++)  
  138.         {  
  139.             que.Enqueue(pNode->m_arrNodePointer[i]);  
  140.         }  
  141.     }  
  142.   
  143.     return 0;  
  144. }  

猜你喜欢

转载自blog.csdn.net/ytlcainiao/article/details/45915251