C#循环顺序队列与链式队列实现详解

Theo
Theo
发布时间:2026-10-14| 5人浏览过
原创

队列是一种特殊的线性表,遵循“先进先出”(FIFO)原则,限制元素仅在表尾添加、在表头删除。本文详细介绍C#中通过数组实现的循环顺序队列(解决空间浪费的伪满问题)和基于链表的链式队列的完整泛型实现。

队列的核心特征与接口设计

队列的本质是将数据存取限制在线性结构的两端:入队(Enqueue)只能在尾部进行,出队(Dequeue)只能在头部进行。这种机制广泛应用于操作系统任务调度、消息缓冲区及算法模拟等场景。

为了实现通用的队列逻辑,首先定义一个泛型接口 IQueue<T>,包含以下基本操作:

  • Count():获取当前元素数量。
  • IsEmpty() / IsFull():判断队列状态。
  • Clear():清空队列。
  • Enqueue(T item):向队列尾部插入元素。
  • Dequeue():从队列头部取出并删除元素。
  • Peek():查看队列头部元素但不删除。
namespace 栈与队列
{
  public interface IQueue<T>
  {
    public int Count();
    public bool IsEmpty();
    public void Clear();
    public void Enqueue(T item);
    public T Dequeue();
    public T Peek();
  }
}

循环顺序队列的实现原理

顺序队列通常使用数组存储。如果使用简单的线性数组,随着元素的出入队,头部会产生大量空闲空间而无法复用,导致数组溢出,这被称为“假溢出”或“伪满”现象。

为了解决这个问题,我们将数组想象成首尾相接的环状结构。当 rear 指针到达数组末尾时,将其重置为 0。但在循环结构中,仅凭 front == rear 无法区分是队空还是队满。通用的解决方案是牺牲数组的一个存储单元:当 (rear + 1) % size == front 时,判定为队满。

循环顺序队列完整代码

以下是处理了边界跳转(rear = 0)、容量判断及计数逻辑的 CSeqQueue<T> 类实现:

using System;
using System.Text;

namespace 栈与队列
{
  /// <summary>
  /// 循环顺序队列,解决普通顺序队列的假溢出问题
  /// </summary>
  public class CSeqQueue<T> : IQueue<T>
  {
    private int maxsize;
    private T[] data;
    private int front; // 指向队头元素的前一个位置
    private int rear;  // 指向队尾元素的位置    

    public CSeqQueue(int size)
    {
      data = new T[size];
      maxsize = size;
      front = rear = -1; // 初始状态均为-1
    }

    public int Count()
    {
      if (rear > front)
      {
        return rear - front;
      }
      else
      {
        // 发生回绕时的计算公式
        return (rear - front + maxsize) % maxsize;
      }
    }

    public bool IsEmpty() { return front == rear; }

    public bool IsFull()
    {
      if (front != -1) // 经历过出队操作后,必须按循环规则判断
      {
        return (rear + 1) % maxsize == front;
      }
      else
      {
        // 初始状态下,如果rear已满则是真满
        return rear == maxsize - 1;
      }
    }

    public void Clear() { front = rear = -1; }

    public void Enqueue(T item)
    {
      if (IsFull())
      {
        Console.WriteLine("Queue is full");
        return;
      }
      // 关键循环逻辑:到达数组末尾则重置为0
      if (rear == maxsize - 1) rear = 0;
      else rear++;

      data[rear] = item;
    }

    public T Dequeue()
    {
      if (IsEmpty())
      {
        Console.WriteLine("Queue is empty");
        return default(T);
      }
      // 关键循环逻辑:front到达末尾重置为0
      if (front == maxsize - 1) front = 0;
      else front++;      

      return data[front];
    }

    public T Peek()
    {
      if (IsEmpty())
      {
        Console.WriteLine("Queue is empty!");
        return default(T);
      }
      // 取下一个位置的元素,同样需要模运算防止越界
      return data[(front + 1) % maxsize];
    }
    //... ToString方法用于调试输出...
  }
}

在此实现中,Enqueue 和 Dequeue 都包含了 if (index == maxsize - 1) index = 0; 这样的逻辑,以确保指针在环形结构中正确流转。

操作示意图解

下图展示了普通顺序队列在经历多次入队出队后的内存分布情况,直观揭示了“伪满”问题的成因:

而通过修改逻辑,将数组视为循环结构后,即便 rear 指到了最末端,也能无缝跳回开头继续利用空闲位置:

链式队列的实现方式

相较于顺序队列需要预留空间和复杂的取模运算,链式队列通过节点引用连接元素,天然具备动态扩容的特性。其核心在于维护两个引用指针:队头的 front 和队尾的 rear。

链表节点定义

每个节点包含数据域和指向下一节点的引用域:

public class Node<T>
{
  public T Data { get; set; }
  public Node<T> Next { get; set; }
  public Node(T data, Node<T> next = null) {
      this.Data = data;
      this.Next = next;
  }
}

链式队列核心逻辑

  • 入队(Enqueue):新建节点。若为空队列,头尾指针均指向该新节点;若不为空,让旧 rear.Next 指向新节点,然后更新 rear 为新节点。
  • 出队(Dequeue):保存当前 front 节点的数据。将 front 移至 front.Next。特别注意的是,如果移动后 front 变为 null(即队列为空),必须同步将 rear 也置为 null。
  • Peek:直接读取 front.Data。
public class LinkQueue<T> : IQueue<T>
{
  private Node<T> front;
  private Node<T> rear;
  private int num;

  public LinkQueue() { front = rear = null; num = 0; }

  public bool IsEmpty() { return front == null; }

  public void Enqueue(T item)
  {
    var q = new Node<T>(item);
    if (rear == null) front = rear = q;
    else
    {
      rear.Next = q;
      rear = q;
    }
    num++;
  }

  public T Dequeue()
  {
    if (IsEmpty()) return default(T);
    Node<T> p = front;
    front = front.Next;
    if (front == null) rear = null; // 重要:清空同步
    num--;
    return p.Data;
  }

  public T Peek() => IsEmpty() ? default(T) : front.Data;
}

以上就是C#数据结构之队列(Quene)实例的详细内容,更多关于C#高级数据结构的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。