代码改变世界

C语言 队列 链式结构 实现

2013-10-31 12:07  wid  阅读(1673)  评论(0编辑  收藏  举报

一个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\n", GetLength(pque), IsEmpty(pque) );
258 
259     ///测试 EnQueue
260     EnQueue( pque, &pt1 );
261     if( IsEmpty(pque) != TRUE )
262         printf( "入队1元素后队列当前长度:%d, 是否为空队列:%d\n", GetLength(pque), IsEmpty(pque) );
263 
264     ///测试 ClearQueue
265     ClearQueue( pque );
266     printf( "清空队列, 当前长度:%d\n", GetLength(pque) );
267 
268     ///入队5元素
269     printf( "\n连续入队5元素..\n" );
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( "\n\n测试DeQueue, 出队元素为:(%d,%d), 出队后队列长度:%d\n", p->x, p->y, GetLength(pque) );
284 
285     ///测试 GetHead
286     if( GetHead(pque, &p) != -1 )
287         printf( "\n测试GetHead, Head元素为(%d,%d)\n", p->x, p->y );
288 
289     ///全部出队
290     printf( "\n执行全部出队...\n" );
291     while( DeQueue(pque, &p) != -1 )
292     {
293         printf( "当前出队:(%d,%d), 队列剩余长度:%d, 是否为空队列%d\n", p->x, p->y, GetLength(pque), IsEmpty(pque) );
294     }
295 
296     ///销毁队列
297     printf( "\n销毁队列...\n" );
298     DestroyQueue( pque );
299 
300     return 0;
301 }

运行测试:

 

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