zoukankan      html  css  js  c++  java
  • C语言 队列 链式结构 实现

    一个C语言链式结构实现的队列 mQueue (GCC编译)。

      1 /**
      2 * @brief C语言实现的链式队列
      3 * @author wid
      4 * @date 2013-10-31
      5 *
      6 * @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
      7 */
      8 
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 
     12 #define TRUE 1
     13 #define FALSE 0
     14 
     15 typedef struct Point2D
     16 {
     17     int x;
     18     int y;
     19 }ElemType;      //元素结构
     20 
     21 typedef struct QNODE
     22 {
     23     ElemType *pe;
     24     struct QNODE *next;
     25 }QueueNode;     //队列节点结构
     26 
     27 typedef struct MQUEUE
     28 {
     29     QueueNode *rear;        //队列尾节点
     30     QueueNode *front;       //队列头节点
     31     int len;                //队列长度
     32 }mQueue;
     33 
     34 //队列方法声明
     35 mQueue *CreateQueue();                          ///创建一个空队列
     36 void DestroyQueue( mQueue *pQueue );            ///销毁队列 pQueue
     37 void ClearQueue( mQueue *pQueue );              ///置空队列 pQueue
     38 int IsEmpty( mQueue *pQueue );                  ///是否为空空队列
     39 int GetLength( mQueue *pQueue );                ///获取队列长度
     40 int EnQueue( mQueue *pQueue, ElemType *pe );    ///将元素pe插入到队尾
     41 int DeQueue( mQueue *pQueue, ElemType **pe );   ///将将队头元素出队
     42 int GetHead( mQueue *pQueue, ElemType **pe );   ///获取队头元素(不出队)
     43 void ForEachQueue( mQueue *pQueue, void (*func)(ElemType *pe) );        ///从队头到队尾依次执行func函数
     44 
     45 
     46 //队列方法实现
     47 /**
     48 * @brief 创建一个空队列
     49 *
     50 * @return 返回指向新创建的队列的指针
     51 */
     52 mQueue *CreateQueue()
     53 {
     54     ///创建队列
     55     mQueue *pQueue = (mQueue *)malloc( sizeof(mQueue) );
     56 
     57     ///令队头指向队尾
     58     pQueue->front = pQueue->rear = (QueueNode *)malloc( sizeof(QueueNode) );
     59 
     60     ///队尾的next节点指向NULL
     61     pQueue->rear->next = NULL;
     62 
     63     ///队头的next节点指向队尾
     64     pQueue->front->next = pQueue->rear;
     65 
     66     ///初始化队长为 0
     67     pQueue->len = 0;
     68 
     69     return pQueue;
     70 }
     71 
     72 /**
     73 * @brief 销毁队列 pQueue
     74 *
     75 * @param pQueue 指向待销毁的队列
     76 */
     77 void DestroyQueue( mQueue *pQueue )
     78 {
     79     QueueNode *tmp = NULL;
     80 
     81     ///释放队列内元素
     82     while( pQueue->front != NULL )
     83     {
     84         tmp = pQueue->front->next;
     85         free( pQueue->front );
     86         pQueue->front = tmp;
     87     }
     88 
     89     ///释放队列
     90     free( pQueue );
     91 }
     92 
     93 /**
     94 * @brief 将队列中的元素全部清除
     95 *
     96 * @param pQueue 指向待置空的队列
     97 */
     98 void ClearQueue( mQueue *pQueue )
     99 {
    100     QueueNode *tmp = NULL;
    101 
    102     ///释放队列内元素(保留一队尾节点)
    103     while( pQueue->front->next != NULL )
    104     {
    105         tmp = pQueue->front->next;
    106         free( pQueue->front );
    107         pQueue->front = tmp;
    108     }
    109 
    110     pQueue->len = 0;
    111 }
    112 
    113 /**
    114 * @brief 是否为空队列
    115 *
    116 * @param pQueue 指向待检测的队列
    117 *
    118 * @return 若为空则返回 TRUE, 否则返回 FALSE
    119 */
    120 int IsEmpty( mQueue *pQueue )
    121 {
    122     return pQueue->len == 0 ? TRUE : FALSE;
    123 }
    124 
    125 /**
    126 * @brief 获取队列长度
    127 *
    128 * @param pQueue 指向待获取长度的队列
    129 *
    130 * @return 返回队列当前长度
    131 */
    132 int GetLength( mQueue *pQueue )
    133 {
    134     return pQueue->len;
    135 }
    136 
    137 /**
    138 * @brief 将元素pe插入到队尾
    139 *
    140 * @param pQueue 指向待入队的队列
    141 * @param pe 指向待插入的元素
    142 *
    143 * @return 插入成功则返回入队后队列的长度, 否则返回 -1
    144 */
    145 int EnQueue( mQueue *pQueue, ElemType *pe )
    146 {
    147     ///请求一个新节点
    148     QueueNode *pNode = (QueueNode *)malloc( sizeof(QueueNode) );
    149 
    150     ///新节点的数据元素指向传入的元素
    151     pNode->pe = pe;
    152 
    153     ///新节点的next节点指向 NULL
    154     pNode->next = NULL;
    155 
    156     ///队尾的next节点指向新节点
    157     pQueue->rear->next = pNode;
    158 
    159     ///令队尾指向新节点
    160     pQueue->rear = pNode;
    161 
    162     return ++pQueue->len;
    163 }
    164 
    165 /**
    166 * @brief 将队头元素出队
    167 *
    168 * @param pQueue 指向待出队的队列
    169 * @param pe 指向接收元素的指针的指针
    170 *
    171 * @return 成功出队后返回出队后队列的长度, 否则返回 -1
    172 */
    173 int DeQueue( mQueue *pQueue, ElemType **pe )
    174 {
    175 
    176     ///队列是否为空
    177     if( pQueue->front == pQueue->rear )
    178         return -1;
    179 
    180     ///得到队头元素
    181     *pe = pQueue->front->next->pe;
    182 
    183     ///令队头指向上一节点
    184     QueueNode *tmp = pQueue->front;
    185     pQueue->front = pQueue->front->next;
    186     free( tmp );
    187 
    188     return --pQueue->len;
    189 }
    190 
    191 /**
    192 * @brief 获取队头元素, 不出栈
    193 *
    194 * @param 指向待获取队头元素的队列
    195 * @param 指向接收出栈元素的指针的指针
    196 *
    197 * @return 获取成功则返回元素在队列中的位置, 否则返回 -1, 且 *pe 指向 NULL
    198 *
    199 * @note 元素位置由 0 计起
    200 */
    201 int GetHead( mQueue *pQueue, ElemType **pe )
    202 {
    203     ///队列是否为空
    204     if( pQueue->front == pQueue->rear )
    205     {
    206         *pe = NULL;
    207         return -1;
    208     }
    209 
    210     ///得到队头元素
    211     *pe = pQueue->front->next->pe;
    212 
    213     return pQueue->len - 1;
    214 }
    215 
    216 /**
    217 * @brief 从队头到队尾对每个元素依次执行 func 函数
    218 *
    219 * @param pQueue 指向待处理的队列
    220 * @param func 回调函数
    221 */
    222 void ForEachQueue( mQueue *pQueue, void (*func)(ElemType *pe) )
    223 {
    224     QueueNode *tmp = pQueue->front;
    225 
    226     ///遍历执行 func
    227     while( tmp != pQueue->rear && (tmp = tmp->next) )
    228     {
    229         func( tmp->pe );
    230     }
    231 }
    232 
    233 //测试
    234 
    235 /**
    236 * @brief 输出元素 pe
    237 */
    238 void display( ElemType *pe )
    239 {
    240     printf( "(%d,%d )", pe->x, pe->y );
    241 }
    242 
    243 int main()
    244 {
    245     ///准备数据元素
    246     ElemType pt1 = { 10, 10 };
    247     ElemType pt2 = { 20, 20 };
    248     ElemType pt3 = { 30, 30 };
    249     ElemType pt4 = { 40, 40 };
    250     ElemType pt5 = { 50, 50 };
    251 
    252     ///测试 CreateQueue
    253     mQueue *pque = CreateQueue();
    254 
    255     ///测试 IsEmpty、GetLength
    256     if( IsEmpty(pque) == TRUE )
    257         printf( "队列当前长度:%d, 是否为空队列:%d
    ", GetLength(pque), IsEmpty(pque) );
    258 
    259     ///测试 EnQueue
    260     EnQueue( pque, &pt1 );
    261     if( IsEmpty(pque) != TRUE )
    262         printf( "入队1元素后队列当前长度:%d, 是否为空队列:%d
    ", GetLength(pque), IsEmpty(pque) );
    263 
    264     ///测试 ClearQueue
    265     ClearQueue( pque );
    266     printf( "清空队列, 当前长度:%d
    ", GetLength(pque) );
    267 
    268     ///入队5元素
    269     printf( "
    连续入队5元素..
    " );
    270     EnQueue( pque, &pt1 );
    271     EnQueue( pque, &pt2 );
    272     EnQueue( pque, &pt3 );
    273     EnQueue( pque, &pt4 );
    274     EnQueue( pque, &pt5 );
    275 
    276     ///测试 ForEachQueue
    277     printf( "测试 ForEachQueue:" );
    278     ForEachQueue( pque, display );
    279 
    280     ///测试 DeQueue
    281     ElemType *p = NULL;
    282     if( DeQueue(pque, &p) != -1 )
    283         printf( "
    
    测试DeQueue, 出队元素为:(%d,%d), 出队后队列长度:%d
    ", p->x, p->y, GetLength(pque) );
    284 
    285     ///测试 GetHead
    286     if( GetHead(pque, &p) != -1 )
    287         printf( "
    测试GetHead, Head元素为(%d,%d)
    ", p->x, p->y );
    288 
    289     ///全部出队
    290     printf( "
    执行全部出队...
    " );
    291     while( DeQueue(pque, &p) != -1 )
    292     {
    293         printf( "当前出队:(%d,%d), 队列剩余长度:%d, 是否为空队列%d
    ", p->x, p->y, GetLength(pque), IsEmpty(pque) );
    294     }
    295 
    296     ///销毁队列
    297     printf( "
    销毁队列...
    " );
    298     DestroyQueue( pque );
    299 
    300     return 0;
    301 }

    运行测试:

    若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。                                                                                                                                                                                                                                                                                                                                                            

  • 相关阅读:
    114.114.114.114和8.8.8.8
    一台电脑双网卡同时上网
    eNSP模拟器
    路由器UPnP
    子网掩码
    网线水晶头制作
    AP (无线访问接入点(WirelessAccessPoint))
    筛选键
    注册表方法修改网络名称
    图片素材网址
  • 原文地址:https://www.cnblogs.com/mr-wid/p/3398907.html
Copyright © 2011-2022 走看看