码迷,mamicode.com
首页 > 其他好文 > 详细

【转】环形队列理论

时间:2015-08-04 15:24:23      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

环形队列是在实际编程极为有用的数据结构,它有如下特点。
   它是一个首尾相连的FIFO的数据结构,采用数组的线性空间,数据组织简单。能很快知道队列是否满为空。能以很快速度的来存取数据
   因为有简单高效的原因,甚至在硬件都实现了环形队列.
 
   环形队列广泛用于网络数据收发,和不同程序间数据交换(比如内核与应用程序大量交换数据,从硬件接收大量数据)均使用了环形队列.
 
一.环形队列实现原理
------------------------------------------------------------
 
  内存上没有环形的结构,因此环形队列实上是数组的线性空间来实现。那当数据到了尾部如何处理呢?它将转回到0位置来处理。这个的转回是通过取模操作来执行的。
   因此环列队列的是逻辑上将数组元素q[0]与q[MAXN-1]连接,形成一个存放队列的环形空间。
   为了方便读写,还要用数组下标来指明队列的读写位置。head/tail.其中head指向可以读的位置,tail指向可以写的位置。
 
技术分享
 
 
 环形队列的关键是判断队列为空,还是为满。当tail追上head时,队列为满时,当head追上tail时,队列为空。但如何知道谁追上谁。还需要一些辅助的手段来判断.
 
   如何判断环形队列为空,为满有两种判断方法。
  一.是附加一个标志位tag
      当head赶上tail,队列空,则令tag=0,
      当tail赶上head,队列满,则令tag=1,
 
  二.限制tail赶上head,即队尾结点与队首结点之间至少留有一个元素的空间。
      队列空:   head==tail
      队列满:   (tail+1)% MAXN ==head
 
 
 
二.附加标志实现算法
-------------------------------------------------------------
 
  采用第一个环形队列有如下结构
1 typedef struct ringq{  
2    int head;   
3    int tail;    
4    int tag ;  
5    int size ;   
6    int space[RINGQ_MAX];   
7     
8 }RINGQ;  

初始化状态: q->head = q->tail = q->tag = 0;

队列为空:(q->head == q->tail) && (q->tag == 0)
队列为满: ((q->head == q->tail) && (q->tag == 1))
入队操作:如队列不满,则写入
     q->tail =  (q->tail + 1) % q->size ;
出队操作:如果队列不空,则从head处读出。
    下一个可读的位置在 q->head =  (q->head + 1) % q->size
 
完整代码
   头文件ringq.h
 1 #ifndef __RINGQ_H__  
 2 #define __RINGQ_H__  
 3   
 4 #ifdef __cplusplus  
 5 extern "C" {  
 6 #endif   
 7   
 8 #define QUEUE_MAX 20  
 9   
10 typedef struct ringq{  
11    int head;   
12    int tail;    
13    int tag ;   
14     int size ;   
15    int space[QUEUE_MAX];   
16 }RINGQ;  
17   
18   
19 extern int ringq_init(RINGQ * p_queue);  
20   
21 extern int ringq_free(RINGQ * p_queue);  
22     
23 extern int ringq_push(RINGQ * p_queue,int data);  
24   
25 extern int ringq_poll(RINGQ * p_queue,int *p_data);  
26   
27 #define ringq_is_empty(q) ( (q->head == q->tail) && (q->tag == 0))  
28   
29 #define ringq_is_full(q) ( (q->head == q->tail) && (q->tag == 1))  
30   
31 #define print_ringq(q) printf("ring head %d,tail %d,tag %d\n", q->head,q->tail,q->tag);  
32 #ifdef __cplusplus  
33 }  
34 #endif   
35   
36 #endif   

 

实现代码 ringq.c
 
 1 #include <stdio.h>  
 2 #include "ringq.h"  
 3   
 4 int ringq_init(RINGQ * p_queue)  
 5 {  
 6    p_queue->size = QUEUE_MAX ;  
 7      
 8    p_queue->head = 0;  
 9    p_queue->tail = 0;  
10      
11    p_queue->tag = 0;  
12      
13    return 0;  
14 }  
15   
16 int ringq_free(RINGQ * p_queue)  
17 {  
18   return 0;  
19 }  
20   
21   
22 int ringq_push(RINGQ * p_queue,int data)  
23 {  
24   print_ringq(p_queue);  
25     
26   if(ringq_is_full(p_queue))  
27    {  
28        
29      printf("ringq is full\n");  
30      return -1;  
31    }  
32         
33    p_queue->space[p_queue->tail] = data;  
34      
35    p_queue->tail = (p_queue->tail + 1) % p_queue->size ;  
36      
37      
38    if(p_queue->tail == p_queue->head)  
39     {  
40        p_queue->tag = 1;  
41     }  
42   
43     return p_queue->tag ;    
44 }  
45   
46 int ringq_poll(RINGQ * p_queue,int * p_data)  
47 {  
48    print_ringq(p_queue);  
49   if(ringq_is_empty(p_queue))  
50    {  
51         
52       printf("ringq is empty\n");  
53      return -1;  
54    }  
55      
56    *p_data = p_queue->space[p_queue->head];  
57      
58    p_queue->head = (p_queue->head + 1) % p_queue->size ;  
59      
60       
61    if(p_queue->tail == p_queue->head)  
62     {  
63        p_queue->tag = 0;  
64     }      
65     return p_queue->tag ;  
66 }  

 

 
测试代码
 1 void test5()  
 2 {  
 3   RINGQ rq, * p_queue;  
 4   int i,data;  
 5     
 6   p_queue = &rq;  
 7     
 8   ringq_init(p_queue);  
 9     
10   for(i=0; i < QUEUE_MAX +2 ; i++)  
11   {  
12      
13    ringq_push(p_queue,i+1);   
14   }   
15       
16   if(ringq_poll(p_queue,&data)>=0)  
17      PRINT_INT(data);  
18     
19   if(ringq_poll(p_queue,&data)>=0)  
20      PRINT_INT(data);  
21     
22   if(ringq_poll(p_queue,&data)>=0)  
23      PRINT_INT(data);  
24     
25   if(ringq_poll(p_queue,&data)>=0)  
26      PRINT_INT(data);  
27     
28   if(ringq_poll(p_queue,&data)>=0)  
29      PRINT_INT(data);  
30     
31   if(ringq_poll(p_queue,&data)>=0)  
32      PRINT_INT(data);  
33     
34   ringq_free(p_queue);  
35 }  
36   
37   
38 void test6()  
39 {  
40   RINGQ rq, * p_queue;  
41   int i,data;  
42     
43   p_queue = &rq;  
44     
45   ringq_init(p_queue);  
46     
47     
48    ringq_push(p_queue,1);   
49      
50    ringq_push(p_queue,2);   
51     
52     
53   if(ringq_poll(p_queue,&data)>=0)  
54      PRINT_INT(data);  
55     
56   if(ringq_poll(p_queue,&data)>=0)  
57      PRINT_INT(data);  
58     
59   if(ringq_poll(p_queue,&data)>=0)  
60      PRINT_INT(data);  
61     
62   if(ringq_poll(p_queue,&data)>=0)  
63      PRINT_INT(data);  
64       
65   ringq_push(p_queue,3);   
66     
67   ringq_push(p_queue,4);   
68     
69   ringq_push(p_queue,5);   
70     
71   if(ringq_poll(p_queue,&data)>=0)  
72      PRINT_INT(data);  
73     
74   if(ringq_poll(p_queue,&data)>=0)  
75      PRINT_INT(data);  
76          
77    ringq_push(p_queue,6);   
78        
79    if(ringq_poll(p_queue,&data)>=0)  
80      PRINT_INT(data);  
81        
82      if(ringq_poll(p_queue,&data)>=0)  
83      PRINT_INT(data);  
84     
85   ringq_free(p_queue);  
86 }  

 

 
三.预留空间环境队列
 
 -------------------------------------------------------------------
 
不采用tag,只留一个空间
  
技术分享 
初始化状态: q->head = q->tail = q->tag = 0;
队列为空:(q->head == q->tail)
队列为满: (((q->tail+1)%q->size) == q->head )
入队操作:如队列不满,则写入
     q->tail =  (q->tail + 1) % q->size ;
出队操作:如果队列不空,则从head处读出。
    下一个可读的位置在 q->head =  (q->head + 1) % q->size
 
头文件
  ringq.h
   
 1 #ifndef __RINGQ_H__  
 2 #define __RINGQ_H__  
 3   
 4 #ifdef __cplusplus  
 5 extern "C" {  
 6 #endif   
 7   
 8 #define RINGQ_MAX 20  
 9   
10 typedef struct ringq{  
11    int head;   
12    int tail;    
13    int size ;   
14    int space[RINGQ_MAX];   
15 }RINGQ;  
16   
17   
18   
19 extern int ringq_init(RINGQ * p_ringq);  
20   
21 extern int ringq_free(RINGQ * p_ringq);  
22   
23 extern int ringq_push(RINGQ * p_ringq,int data);  
24   
25 extern int ringq_poll(RINGQ * p_ringq,int * p_data);  
26   
27 #define ringq_is_empty(q) (q->head == q->tail)  
28   
29 #define ringq_is_full(q) (((q->tail+1)%q->size) == q->head )  
30   
31 #define print_ringq2(q,d) printf("ring head %d,tail %d,data %d\n", q->head,q->tail,d);  
32   
33 #ifdef __cplusplus  
34 }  
35 #endif   
36   
37 #endif   

 

 

实现代码ringq.c

 

 1 #include <stdio.h>  
 2   
 3 #include "ringq.h"  
 4   
 5 int ringq_init(RINGQ * p_ringq)  
 6 {  
 7   p_ringq->size = RINGQ_MAX;  
 8     
 9   p_ringq->head = 0;  
10   p_ringq->tail = 0;  
11     
12   return p_ringq->size;  
13 }  
14   
15 int ringq_free(RINGQ * p_ringq)  
16 {  
17   return 0;  
18 }  
19   
20   
21 int ringq_push(RINGQ * p_ringq,int data)  
22 {  
23    print_ringq(p_ringq,data);  
24      
25    if(ringq_is_full(p_ringq))  
26      {  
27          printf("ringq is full,data %d\n",data);  
28            return -1;  
29      }  
30            
31    p_ringq->space[p_ringq->tail] = data;  
32      
33    p_ringq->tail = (p_ringq->tail + 1) % p_ringq->size ;     
34       
35     return p_ringq->tail ;  
36 }  
37   
38   
39 int ringq_poll(RINGQ * p_ringq,int * p_data)  
40 {  
41    print_ringq(p_ringq,-1);  
42   if(ringq_is_empty(p_ringq))  
43    {  
44      printf("ringq is empty\n");  
45      return -1;  
46    }  
47      
48    *p_data = p_ringq->space[p_ringq->head];  
49      
50    p_ringq->head = (p_ringq->head + 1) % p_ringq->size ;  
51      
52    return p_ringq->head;  
53 } 

 

【转】环形队列理论

标签:

原文地址:http://www.cnblogs.com/codecamel/p/4701882.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!