zoukankan      html  css  js  c++  java
  • 【转】环形队列理论(C语言)

    环形队列是在实际编程极为有用的数据结构,它有如下特点。
       它是一个首尾相连的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 typedef struct ringq{  
    10    int head;   
    11    int tail;    
    12    int tag ;   
    13     int size ;   
    14    int space[QUEUE_MAX];   
    15 }RINGQ;  
    16   
    17   
    18 extern int ringq_init(RINGQ * p_queue);  
    19 extern int ringq_free(RINGQ * p_queue);    
    20 extern int ringq_push(RINGQ * p_queue,int data);  
    21 extern int ringq_poll(RINGQ * p_queue,int *p_data);  
    22 #define ringq_is_empty(q) ( (q->head == q->tail) && (q->tag == 0))  
    23 #define ringq_is_full(q) ( (q->head == q->tail) && (q->tag == 1))  
    24 #define print_ringq(q) printf("ring head %d,tail %d,tag %d
    ", q->head,q->tail,q->tag);  
    25 #ifdef __cplusplus  
    26 }  
    27 #endif   
    28   
    29 #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    p_queue->head = 0;  
     8    p_queue->tail = 0;      
     9    p_queue->tag = 0;       
    10    return 0;  
    11 }  
    12   
    13 int ringq_free(RINGQ * p_queue)  
    14 {  
    15     return 0;  
    16 }  
    17 //Write data to the queue   
    18 int ringq_push(RINGQ * p_queue,int data)  
    19 {  
    20     print_ringq(p_queue);      
    21     if(ringq_is_full(p_queue))  
    22     {       
    23         printf("ringq is full
    ");  
    24         return -1;  
    25     }         
    26     p_queue->space[p_queue->tail] = data;      
    27     p_queue->tail = (p_queue->tail + 1) % p_queue->size ;           
    28     if(p_queue->tail == p_queue->head)  
    29     {  
    30         p_queue->tag = 1;  
    31     }   
    32     return p_queue->tag ;    
    33 }  
    34 //Get data from the queue  
    35 int ringq_poll(RINGQ * p_queue,int * p_data)  
    36 {  
    37     print_ringq(p_queue);  
    38     if(ringq_is_empty(p_queue))  
    39     {        
    40         printf("ringq is empty
    ");  
    41         return -1;  
    42     }      
    43     *p_data = p_queue->space[p_queue->head];     
    44     p_queue->head = (p_queue->head + 1) % p_queue->size ;   
    45     if(p_queue->tail == p_queue->head)  
    46     {  
    47         p_queue->tag = 0;  
    48     }      
    49     return p_queue->tag ;  
    50 }
     
     
    测试代码
     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 extern int ringq_init(RINGQ * p_ringq);  
    19 extern int ringq_free(RINGQ * p_ringq);   
    20 extern int ringq_push(RINGQ * p_ringq,int data);    
    21 extern int ringq_poll(RINGQ * p_ringq,int * p_data);  
    22   
    23 #define ringq_is_empty(q) (q->head == q->tail)    
    24 #define ringq_is_full(q) (((q->tail+1)%q->size) == q->head )   
    25 #define print_ringq2(q,d) printf("ring head %d,tail %d,data %d
    ", q->head,q->tail,d);  
    26  
    27 #ifdef __cplusplus  
    28 }  
    29 #endif   
    30   
    31 #endif
     

    实现代码ringq.c

     1 #include <stdio.h>  
     2 #include "ringq.h"  
     3   
     4 int ringq_init(RINGQ * p_ringq)  
     5 {  
     6     p_ringq->size = RINGQ_MAX;      
     7     p_ringq->head = 0;  
     8     p_ringq->tail = 0;    
     9     return p_ringq->size;  
    10 }  
    11   
    12 int ringq_free(RINGQ * p_ringq)  
    13 {  
    14     return 0;  
    15 }  
    16   
    17   
    18 int ringq_push(RINGQ * p_ringq,int data)  
    19 {  
    20     print_ringq(p_ringq,data);     
    21     if(ringq_is_full(p_ringq))  
    22     {  
    23         printf("ringq is full,data %d
    ",data);  
    24         return -1;  
    25     }          
    26     p_ringq->space[p_ringq->tail] = data;       
    27     p_ringq->tail = (p_ringq->tail + 1) % p_ringq->size ;           
    28     return p_ringq->tail ;  
    29 }  
    30   
    31   
    32 int ringq_poll(RINGQ * p_ringq,int * p_data)  
    33 {  
    34     print_ringq(p_ringq,-1);  
    35     if(ringq_is_empty(p_ringq))  
    36     {  
    37         printf("ringq is empty
    ");  
    38         return -1;  
    39     }       
    40     *p_data = p_ringq->space[p_ringq->head];       
    41     p_ringq->head = (p_ringq->head + 1) % p_ringq->size ;      
    42     return p_ringq->head;  
    43 }
  • 相关阅读:
    OpenCV-Python图形图像处理:利用黑帽去除图像浅色水印
    单片机实验四:定时器控制发光二极管的亮灭+简单输出连续矩形脉冲
    实验5 linux网络编程
    第十六届全国大学智能汽车竞赛竞速比赛规则-讨论稿
    写给自己的TypeScript 入门小纲
    写给自己的TypeScript 入门小纲
    Node.js自学笔记之回调函数
    Node.js自学笔记之回调函数
    来简书坚持一个月日更之后
    全选或者单选checkbox的值动态添加到div
  • 原文地址:https://www.cnblogs.com/codecamel/p/4701882.html
Copyright © 2011-2022 走看看