环形队列实现原理

环形队列实现原理

分类: Linux系统开发 3419人阅读 评论(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;  
typedef struct ringq{
   int head; /* 头部,出队列方向*/
   int tail; /* 尾部,入队列方向*/ 
   int tag ;
   int size ; /* 队列总尺寸 */
   int space[RINGQ_MAX]; /* 队列空间 */
  
}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.   第一种设计方法: 
  20.      当head == tail 时,tag = 0 为空,等于 = 1 为满。 
  21. */  
  22.   
  23. extern int ringq_init(RINGQ * p_queue);  
  24.   
  25. extern int ringq_free(RINGQ * p_queue);  
  26.   
  27.   
  28. /* 加入数据到队列 */  
  29. extern int ringq_push(RINGQ * p_queue,int data);  
  30.   
  31. /* 从队列取数据 */  
  32. extern int ringq_poll(RINGQ * p_queue,int *p_data);  
  33.   
  34.   
  35. #define ringq_is_empty(q) ( (q->head == q->tail) && (q->tag == 0))  
  36.   
  37. #define ringq_is_full(q) ( (q->head == q->tail) && (q->tag == 1))  
  38.   
  39. #define print_ringq(q) printf("ring head %d,tail %d,tag %d\n", q->head,q->tail,q->tag);  
  40. #ifdef __cplusplus  
  41. }  
  42. #endif   
  43.   
  44. #endif /* __RINGQ_H__ */  
#ifndef __RINGQ_H__
#define __RINGQ_H__

#ifdef __cplusplus
extern "C" {
#endif 

#define QUEUE_MAX 20

typedef struct ringq{
   int head; /* 头部,出队列方向*/
   int tail; /* 尾部,入队列方向*/ 
   int tag ; /* 为空还是为满的标志位*/
    int size ; /* 队列总尺寸 */
   int space[QUEUE_MAX]; /* 队列空间 */
}RINGQ;

/* 
  第一种设计方法:
     当head == tail 时,tag = 0 为空,等于 = 1 为满。
*/

extern int ringq_init(RINGQ * p_queue);

extern int ringq_free(RINGQ * p_queue);


/* 加入数据到队列 */
extern int ringq_push(RINGQ * p_queue,int data);

/* 从队列取数据 */
extern int ringq_poll(RINGQ * p_queue,int *p_data);


#define ringq_is_empty(q) ( (q->head == q->tail) && (q->tag == 0))

#define ringq_is_full(q) ( (q->head == q->tail) && (q->tag == 1))

#define print_ringq(q) printf("ring head %d,tail %d,tag %d\n", q->head,q->tail,q->tag);
#ifdef __cplusplus
}
#endif 

#endif /* __RINGQ_H__ */


实现代码 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. }  
#include <stdio.h>
#include "ringq.h"

int ringq_init(RINGQ * p_queue)
{
   p_queue->size = QUEUE_MAX ;
   
   p_queue->head = 0;
   p_queue->tail = 0;
   
   p_queue->tag = 0;
   
   return 0;
}

int ringq_free(RINGQ * p_queue)
{
  return 0;
}


int ringq_push(RINGQ * p_queue,int data)
{
  print_ringq(p_queue);
  
  if(ringq_is_full(p_queue))
   {
     
     printf("ringq is full\n");
     return -1;
   }
      
   p_queue->space[p_queue->tail] = data;
   
   p_queue->tail = (p_queue->tail + 1) % p_queue->size ;
   
   /* 这个时候一定队列满了*/
   if(p_queue->tail == p_queue->head)
    {
       p_queue->tag = 1;
    }

    return p_queue->tag ;  
}

int ringq_poll(RINGQ * p_queue,int * p_data)
{
   print_ringq(p_queue);
  if(ringq_is_empty(p_queue))
   {
      
      printf("ringq is empty\n");
     return -1;
   }
   
   *p_data = p_queue->space[p_queue->head];
   
   p_queue->head = (p_queue->head + 1) % p_queue->size ;
   
    /* 这个时候一定队列空了*/
   if(p_queue->tail == p_queue->head)
    {
       p_queue->tag = 0;
    }    
    return p_queue->tag ;
}


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

/* 测试第一种环形队列,更加复杂的情况*/
void test6()
{
  RINGQ rq, * p_queue;
  int i,data;
  
  p_queue = &rq;
  
  ringq_init(p_queue);
  
  
   ringq_push(p_queue,1); 
   
   ringq_push(p_queue,2); 
  
  
  if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
  
  if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
  
  if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
  
  if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
    
  ringq_push(p_queue,3); 
  
  ringq_push(p_queue,4); 
  
  ringq_push(p_queue,5); 
  
  if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
  
  if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
       
   ringq_push(p_queue,6); 
     
   if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
     
     if(ringq_poll(p_queue,&data)>=0)
     PRINT_INT(data);
  
  ringq_free(p_queue);
}


 
三.预留空间环境队列
 
 -------------------------------------------------------------------
 
不采用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.   取消tag .限制读与写之间至少要留一个空间 
  19.   队列空 head == tail . 
  20.   队列满是 (tail+1)%MAX == head   
  21.   初始化是head = tail = 0;    
  22. */  
  23.   
  24. extern int ringq_init(RINGQ * p_ringq);  
  25.   
  26. extern int ringq_free(RINGQ * p_ringq);  
  27.   
  28. extern int ringq_push(RINGQ * p_ringq,int data);  
  29.   
  30. extern int ringq_poll(RINGQ * p_ringq,int * p_data);  
  31.   
  32. #define ringq_is_empty(q) (q->head == q->tail)  
  33.   
  34. #define ringq_is_full(q) (((q->tail+1)%q->size) == q->head )  
  35.   
  36. #define print_ringq2(q,d) printf("ring head %d,tail %d,data %d\n", q->head,q->tail,d);  
  37.   
  38. #ifdef __cplusplus  
  39. }  
  40. #endif   
  41.   
  42. #endif /* __QUEUE_H__ */  
#ifndef __RINGQ_H__
#define __RINGQ_H__

#ifdef __cplusplus
extern "C" {
#endif 

#define RINGQ_MAX 20

typedef struct ringq{
   int head; /* 头部,出队列方向*/
   int tail; /* 尾部,入队列方向*/ 
   int size ; /* 队列总尺寸 */
   int space[RINGQ_MAX]; /* 队列空间 */
}RINGQ;

/*
  取消tag .限制读与写之间至少要留一个空间
  队列空 head == tail .
  队列满是 (tail+1)%MAX == head  
  初始化是head = tail = 0;   
*/

extern int ringq_init(RINGQ * p_ringq);

extern int ringq_free(RINGQ * p_ringq);

extern int ringq_push(RINGQ * p_ringq,int data);

extern int ringq_poll(RINGQ * p_ringq,int * p_data);

#define ringq_is_empty(q) (q->head == q->tail)

#define ringq_is_full(q) (((q->tail+1)%q->size) == q->head )

#define print_ringq2(q,d) printf("ring head %d,tail %d,data %d\n", q->head,q->tail,d);

#ifdef __cplusplus
}
#endif 

#endif /* __QUEUE_H__ */

 

实现代码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. }  
#include <stdio.h>

#include "ringq.h"

int ringq_init(RINGQ * p_ringq)
{
  p_ringq->size = RINGQ_MAX;
  
  p_ringq->head = 0;
  p_ringq->tail = 0;
  
  return p_ringq->size;
}

int ringq_free(RINGQ * p_ringq)
{
  return 0;
}

/* 往队列加入数据 */
int ringq_push(RINGQ * p_ringq,int data)
{
   print_ringq(p_ringq,data);
   
   if(ringq_is_full(p_ringq))
     {
         printf("ringq is full,data %d\n",data);
           return -1;
     }
         
   p_ringq->space[p_ringq->tail] = data;
   
   p_ringq->tail = (p_ringq->tail + 1) % p_ringq->size ;   
    
    return p_ringq->tail ;
}


int ringq_poll(RINGQ * p_ringq,int * p_data)
{
   print_ringq(p_ringq,-1);
  if(ringq_is_empty(p_ringq))
   {
     printf("ringq is empty\n");
     return -1;
   }
   
   *p_data = p_ringq->space[p_ringq->head];
   
   p_ringq->head = (p_ringq->head + 1) % p_ringq->size ;
   
   return p_ringq->head;
}

作者: Andrew Huang bluedrum@163.com
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
环形指针队列是一种非常常见的数据结构,通常用于解决多任务并发处理、缓存数据等问题。它的核心思想是将队列中的元素存储在一个环形数组中,通过两个指针front和rear分别指向队头和队尾,实现入队和出队操作。 具体实现原理如下: 1. 定义环形队列结构体,包含队列数组、队头指针front、队尾指针rear、队列长度等信息。 ``` #define MAXSIZE 100 typedef struct { int data[MAXSIZE]; int front; int rear; int size; } CircleQueue; ``` 2. 初始化队列,将队头和队尾指针都指向0。 ``` void InitQueue(CircleQueue *queue) { queue->front = 0; queue->rear = 0; queue->size = 0; } ``` 3. 判断队列是否为,当队头指针等于队尾指针时,队列为。 ``` int IsEmpty(CircleQueue *queue) { return queue->front == queue->rear; } ``` 4. 判断队列是否满,当队尾指针加1等于队头指针时,队列满。 ``` int IsFull(CircleQueue *queue) { return (queue->rear + 1) % MAXSIZE == queue->front; } ``` 5. 入队操作,将元素插入队尾,队尾指针加1,当队尾指针等于数组长度时,将其置为0。 ``` void EnQueue(CircleQueue *queue, int x) { if (IsFull(queue)) { printf("Queue is full.\n"); return; } queue->data[queue->rear] = x; queue->rear = (queue->rear + 1) % MAXSIZE; queue->size++; } ``` 6. 出队操作,将队头元素弹出,队头指针加1,当队头指针等于数组长度时,将其置为0。 ``` int DeQueue(CircleQueue *queue) { if (IsEmpty(queue)) { printf("Queue is empty.\n"); return -1; } int x = queue->data[queue->front]; queue->front = (queue->front + 1) % MAXSIZE; queue->size--; return x; } ``` 这样,就完成了环形指针队列的实现。需要注意的是,由于在环形队列中,队尾指针可能会超过数组长度,因此需要使用取模运算将其限制在数组范围内。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值