OpenGuass源码中对circularqueue.h的分析

对circularqueue.h的分析

引言

循环队列(Circular Queue)是一种队列(Queue)的数据结构,它具有环形的结构,可以解决普通队列在尾部插入元素后需要移动元素的问题。循环队列的特点是在队列的前后端都有指针,当队列满时,新元素会从队列的头部重新开始插入,形成一个环。

以下是关于循环队列的一些重要概念和操作:

  1. 队列指针:循环队列通常有两个指针,一个指向队列的头部,称为front,另一个指向队列的尾部,称为rear。

  2. 初始状态:循环队列在初始状态时,front 和 rear 都被设置为 -1,表示队列为空。

  3. 入队(Enqueue):向循环队列中插入元素时,将元素放置在rear指针所指的位置,并将rear指针向后移动。如果队列已满,就需要考虑循环的情况,即将rear指针重新定位到队列的头部。

  4. 出队(Dequeue):从循环队列中删除元素时,将元素从front指针所指的位置移出,并将front指针向后移动。如果队列为空,就不能执行出队操作。

  5. 队列满与队列空:循环队列的满和空状态之间的差别在于rear指针与front指针之间的距离。如果rear指针在front指针的下一个位置,队列被认为是满的;如果front和rear指针都等于-1,队列被认为是空的。

  6. 队列大小:循环队列的大小通常在创建时固定,一旦队列满了,就无法再添加更多的元素,除非先出队。

循环队列的主要优点是能够更高效地利用存储空间,因为它允许在队列满时重用之前出队的位置。这在某些应用中很有用,比如缓冲区管理和任务调度等。

代码

#ifndef Circular_QUEUE_H
#define Circular_QUEUE_H

#include "postgres.h"

class CircularQueue : public BaseObject {
public:
    CircularQueue(int size, MemoryContext context); /* create a queue with size */
    ~CircularQueue();

    void Init();
    void Destroy();
    bool LockFreeEnQueue(void* elem); /* append elem to the queue */

    const uint32 GetStart() const;              /* get the start  */
    void SetStart(uint32 index);                /* set the start */
    const uint32 GetEnd() const;                /* get the end  */
    const bool IsFull();                        /* if the queue is full */
    uint32 GetLength(uint32 start, uint32 end); /* get the length of queue */
    void QueueTraverse();                       /* traverse the queue */
    void* GetElem(int n);                       /* get nth element in the queue */
    MemoryContext GetContext();                 /* get the memory context of this queue */
public:
    uint32 head;            /* the head of the queue */
    volatile uint32 tail;   /* the tail of the queue */
    uint32 capacity;    /* the capacity of the queue */
    void** queue;    /* the queue */
    MemoryContext cxt;    /* the memory context of the queue */
};

#endif /* Circular_QUEUE_H */

image-20230919120456639

这段代码是一个C++语言实现的循环队列的头文件,实现了循环队列的常规操作,包括:初始化、销毁、入队、获取队列长度、遍历队列、获取队列中第n个元素等。

循环队列是一种常用的数据结构,它能在固定大小的缓冲区中存储和操作元素,并且可以循环使用该区域,类似于环形链表。循环队列的实现可用于进行轮询、缓存、缓冲区等操作,是多个并发线程同步访问任务的常用数据结构。

该头文件包含了类CircularQueue的定义,该类继承自BaseObject(该文件中未定义)。实现了循环队列的主要数据及方法,包括队列头和尾指针head、tail、队列容量capacity、队列元素指针queue、内存上下文cxt等,支持初始化、释放、入队、获取队列长度、遍历、获取队列中第n个元素等常规操作。

示例

下面是一个使用C++语言实现的简单循环队列的例子:

#include <iostream>

int main() {
    CircularQueue cq(5);
    cq.Init();	// 初始化栈
    // 入栈1 2 3 4 5
    cq.enqueue(1);
    cq.enqueue(2);
    cq.enqueue(3);
    cq.enqueue(4);
    cq.enqueue(5);
    
    cq.display();  // 输出: 1 2 3 4 5
    
    cq.dequeue();  // 出栈
    cq.dequeue();  // 出栈 
    
    cq.display();  // 输出: 3 4 5
    cq.enqueue(6);
    cq.display();  // 输出: 3 4 5 6
	
    cq.Destroy();  // 销毁栈
    return 0;
}

假设我们有一个大小为5的循环队列,初始状态下队列为空,front 和 rear 指针都为-1。

  1. 初始状态

    • 队列大小:5
    • front:-1
    • rear:-1
  2. 入队操作:我们开始向队列中添加一些元素。

    • Enqueue(1):将元素1添加到队列,此时 frontrear 都为0。

      队列状态:[1, _, _, _, _]
      front: 0
      rear: 0
      
    • Enqueue(2):添加元素2到队列,rear 向后移动。

      队列状态:[1, 2, _, _, _]
      front: 0
      rear: 1
      
    • Enqueue(3):添加元素3到队列,rear 再次向后移动。

      队列状态:[1, 2, 3, _, _]
      front: 0
      rear: 2
      
    • Enqueue(4):添加元素4到队列,rear 再次向后移动。

      队列状态:[1, 2, 3, 4, _]
      front: 0
      rear: 3
      
    • Enqueue(5):添加元素5到队列,rear 再次向后移动,此时队列已满。

      队列状态:[1, 2, 3, 4, 5]
      front: 0
      rear: 4
      
  3. 出队操作:现在,我们开始出队元素。

    • Dequeue():移除队列的第一个元素,即1,并将 front 向后移动。

      队列状态:[_, 2, 3, 4, 5]
      front: 1
      rear: 4
      
    • Dequeue():移除队列的下一个元素,即2,front 再次向后移动。

      队列状态:[_, _, 3, 4, 5]
      front: 2
      rear: 4
      
  4. 再次入队:现在,队列中有空闲位置,可以再次入队。

    • Enqueue(6):将元素6添加到队列,rear 向后移动。

      队列状态:[6, _, 3, 4, 5]
      front: 2
      rear: 0
      
    • Enqueue(7):添加元素7到队列,rear 再次向后移动。

      队列状态:[6, 7, 3, 4, 5]
      front: 2
      rear: 1
      

此时,循环队列已满,无法继续入队,直到有元素出队为止。

综上:

  • 循环队列通过利用环形结构,可以高效地管理元素的顺序。
  • 入队操作会将元素添加到 rear 指针所指的位置,出队操作会将元素从 front 指针所指的位置移除。
  • 队列满时,rear 指针会绕回队列的开头,从而实现环形特性。
  • 队列空时,frontrear 指针都为-1。
  • 循环队列允许元素在队列头部和尾部之间循环移动,避免了数据搬移的开销,因此在某些应用中效率较高。

总结

循环队列(Circular Queue)是一种队列(Queue)的数据结构,与普通队列不同之处在于它具有环形结构,允许在队列满时重用之前出队的位置。以下是循环队列的主要特点和总结要点:

  1. 环形结构:循环队列使用一个数组或链表来存储元素,并且队列的前后端都有指针。当队列满时,新元素会从队列的头部重新开始插入,形成一个环。

  2. 指针:循环队列通常包括两个指针,即 frontrear,分别指向队列的前端和后端。这些指针帮助确定队列的状态和位置。

  3. 入队操作:将元素插入循环队列时,将元素放置在 rear 指针所指的位置,并将 rear 指针向后移动。如果队列已满,就需要考虑循环的情况,即将 rear 指针重新定位到队列的头部。

  4. 出队操作:从循环队列中删除元素时,将元素从 front 指针所指的位置移出,并将 front 指针向后移动。如果队列为空,就不能执行出队操作。

  5. 队列满与队列空:循环队列的满和空状态之间的差别在于 rear 指针与 front 指针之间的距离。如果 rear 指针在 front 指针的下一个位置,队列被认为是满的;如果 frontrear 指针都等于-1,队列被认为是空的。

  6. 队列大小:循环队列的大小通常在创建时固定,一旦队列满了,就无法再添加更多的元素,除非先出队。

  7. 优点:循环队列能够更高效地利用存储空间,因为它允许在队列满时重用之前出队的位置,而不需要移动所有元素。

  8. 应用:循环队列常用于需要循环缓冲区管理、任务调度和数据流处理等应用场景,其中高效管理元素的顺序是至关重要的。

ear` 指针都等于-1,队列被认为是空的。

  1. 队列大小:循环队列的大小通常在创建时固定,一旦队列满了,就无法再添加更多的元素,除非先出队。

  2. 优点:循环队列能够更高效地利用存储空间,因为它允许在队列满时重用之前出队的位置,而不需要移动所有元素。

  3. 应用:循环队列常用于需要循环缓冲区管理、任务调度和数据流处理等应用场景,其中高效管理元素的顺序是至关重要的。

总之,循环队列是一种常见且有用的数据结构,可用于解决队列满时的元素管理问题,并且在实际编程中经常用于解决各种问题。对于需要高效地管理元素的环境,循环队列是一个非常有用的工具。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值