C# 队列实现

本文探讨了循环队列和链队列两种数据结构的实现,指出它们在时间复杂度上均为O(1),但在空间利用和灵活性上有差异。循环队列在已知最大长度时较为高效,但可能导致空间浪费;链队列虽然有额外的指针开销,但更加灵活。总结建议,如果最大长度确定,选择循环队列,否则选择链队列。同时,提供了Java代码实现来展示两种队列的操作方法。
摘要由CSDN通过智能技术生成

队列实现比栈复杂一点,同样也是特殊的线性表,有顺序存储和链式存储。

参考大话数据结构

两种方式在时间上都是O(1),循环队列开辟了空间暂时不释放,链队列在申请和释放有一定的时间开销,入队出队频繁,会有细微差异。
空间上,循环队列可能会造成空间浪费,链队列虽然有指针节点的开销,可以接受,更灵活。

总结:在确定最大长度的情况下,建议循环队列(也要视情况定),不确定则采用链队列。

节点类:和栈的节点类一样


public class QueueNode<T> 
{
    private T data;
    private QueueNode<T> next;
    public T Data
    {
        get
        {
            return data;
        }
        set
        {
            data = value;
        }
    }
    public QueueNode<T> Next
    {
        get
        {
            return next;
        }

        set
        {
            next = value;
        }
    }
    public QueueNode()
    {
        data = default;
        next = null;
    }
    public QueueNode(T data, QueueNode<T> next)
    {
        this.data = data;
        this.next = next;
    }
    public QueueNode(T data)
    {
        this.data = data;
        this.next = null;
    }
    public QueueNode(QueueNode<T> next)
    {
        this.next = next;
    }
}

顺序循环队列:采用数组(List也可以),跟踪队头、队尾指针。


using System;

// 循环队列
public class CircularQueue<T>
{
    private QueueNode<T>[] arr;

    private int count;

    public int Count
    {
        get { return count; }
        set { count = value; }
    }

    //队头索引:从队头取数据
    private int front;
    //队尾索引:指向下一个可用的位置
    private int rear;

    public CircularQueue(int cap)
    {
        arr = new QueueNode<T>[cap];
        front = 0;
        rear = 0;
    }

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


    //留一个空间,避免判断是空还是满
    public bool IsFull()
    {       
        return (rear + 1) % arr.Length == front;
    }

    public void EnQueue(T data)
    {
        if (IsFull())
        {
            throw new System.Exception("满了!");
            //return;
        }
       

        QueueNode<T> node = new(data);

        arr[rear++] = node;

        if (rear >= arr.Length)
            rear %= arr.Length;

        

        count++;
    }

    public T DeQueue()
    {
        if (IsEmpty())
        {
            throw new System.Exception("空了!");
            //return default;
        }
       
        var node = arr[front];

        arr[front++] = null;

        if (front >= arr.Length)
            front %= arr.Length;

        count--;
        
        return node.Data;
    }

    public void Clear()
    {
        Array.Clear(arr, 0, arr.Length);
        front = 0;
        rear = 0;
    }

    public T Peek()
    {
        return arr[front].Data;
    }
}

链队列:保留了头结点方便操作(front节点未存数据,第一个节点是front.Next),其实也可以不要。



public class LinkedQueue<T>
{
    private QueueNode<T> front;
    private QueueNode<T> rear; 

    public LinkedQueue()
    { 
        front = new QueueNode<T>();
        rear = front;
    }

    private int count;

    public int Count
    {
        get { return count; }
        set { count = value; }
    }


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

    public void EnQueue(T data)
    {       
        QueueNode<T> node = new(data);
        rear.Next = node;
        rear = node;

        count++;
    }

    public T DeQueue()
    {
	 	if (IsEmpty())
        {
            //throw new System.Exception("空了");
            return default;
        }
        
        QueueNode<T> node = front.Next;

        front.Next = front.Next.Next;

        count--;

        return node.Data;
    }

    public void Clear()
    {
        front = rear;
        front.Next = null;
    }

    public T Peek()
    {
        return front.Next.Data;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值