队列
背景
今天复习顺序结构实现的队列、链表结构实现的队列以及利用数组实现的循环队列
基本理论
- 队列的定义:队列是指 插入操作在一端(队尾)进行、删除操作在另一端(队首)进行的线性表。即先进先出线性表。
例子:
- 队列可进行的操作:
代码实现
队列可进行的操作(定义接口)
public interface IQueue<T> where T : IComparable<T>
{
int Length { get; } // 获取元素个数
T QueueFront { get; } // 获取队首元素
void EnQueue(T data); // 入队
void DeQueue(); // 出队
void Clear(); // 清空队列
bool IsEmpty(); // 判断队列是否为空
}
顺序结构实现的队列
利用顺序结构实现的线性表来实现队列
/// <summary>
/// 顺序结构实现队列
/// </summary>
/// <typeparam name="T"></typeparam>
public class SeqQueue<T> : IQueue<T> where T : IComparable<T>
{
private readonly SeqList<T> _lst;
/// <summary>
/// 获取元素个数
/// </summary>
public int Length
{
get
{
return _lst.Length;
}
}
/// <summary>
/// 获取队首元素
/// </summary>
public T QueueFront
{
get
{
if (_lst.Length == 0)
throw new Exception("队列为空");
return _lst[0];
}
}
/// <summary>
/// 队列最大容量
/// </summary>
public int MaxSize
{
get
{
return _lst.MaxSize;
}
}
public SeqQueue(int max)
{
if (max <= 0)
throw new ArgumentOutOfRangeException(nameof(max));
_lst = new SeqList<T>(max);
}
/// <summary>
/// 元素入队
/// </summary>
/// <param name="data"></param>
public void EnQueue(T data)
{
if (_lst.Length == MaxSize)
throw new Exception("队列已满");
_lst.Insert(Length, data);
}
/// <summary>
/// 元素出队
/// </summary>
public void DeQueue()
{
if (_lst.Length == 0)
throw new Exception("队列为空");
_lst.Remove(0);
}
/// <summary>
/// 判断队列是否为空
/// </summary>
/// <returns></returns>
public bool IsEmpty()
{
return _lst.IsEmpty();
}
/// <summary>
/// 清空队列
/// </summary>
public void Clear()
{
_lst.Clear();
}
}
链表实现的队列
利用链表这种数据结构来实现队列。
/// <summary>
/// 利用链表实现队列
/// </summary>
/// <typeparam name="T"></typeparam>
public class LinkQueue<T> : IQueue<T> where T : IComparable<T>
{
private readonly SLinkList<T> _lst;
/// <summary>
/// 获取元素个数
/// </summary>
public int Length
{
get
{
return _lst.Length;
}
}
/// <summary>
/// 获取队首元素
/// </summary>
public T QueueFront
{
get
{
if (_lst.IsEmpty())
throw new Exception("队列为空,不能获取队首元素");
return _lst[0];
}
}
public LinkQueue()
{
_lst = new SLinkList<T>();
}
/// <summary>
/// 入队
/// </summary>
/// <param name="data"></param>
public void EnQueue(T data)
{
_lst.InsertAtRear(data);
}
/// <summary>
/// 出队
/// </summary>
public void DeQueue()
{
if (_lst.IsEmpty())
throw new Exception("队列为空,无法出队");
_lst.Remove(0);
}
/// <summary>
/// 判断队列是否为空
/// </summary>
/// <returns></returns>
public bool IsEmpty()
{
return _lst.IsEmpty();
}
/// <summary>
/// 清空队列
/// </summary>
public void Clear()
{
_lst.Clear();
}
}
利用数组实现的循环队列
循环队列是一种特殊的队列,其队首队尾的位置是移动的。而普通队列,队首位置为0,队尾位置为Length。
如图:
/// <summary>
/// 利用数组实现的循环队列
/// </summary>
/// <typeparam name="T"></typeparam>
public class CSeqQueue<T> : IQueue<T> where T : IComparable<T>
{
private int _pFront; // 队首位置
private int _pRear; // 队尾位置
private readonly T[] _dataSet; // 数组
/// <summary>
/// 获取元素个数
/// </summary>
public int Length { get; private set; }
public int MaxSize { get; }
/// <summary>
/// 获取队首元素
/// </summary>
public T QueueFront
{
get
{
if (Length == 0)
throw new Exception("循环队列为空,无法获取队首元素");
return _dataSet[_pFront];
}
}
public CSeqQueue(int max)
{
if (max <= 0)
throw new ArgumentOutOfRangeException(nameof(max));
MaxSize = max;
_pFront = 0;
_pRear = 0;
_dataSet = new T[max];
}
/// <summary>
/// 元素入队
/// </summary>
/// <param name="data"></param>
public void EnQueue(T data)
{
if (Length == MaxSize)
throw new Exception("队列已满,无法入队");
_dataSet[_pRear] = data;
_pRear = (_pRear + 1) % MaxSize; // 循环也就在于此
Length++;
}
/// <summary>
/// 元素出队
/// </summary>
public void DeQueue()
{
if (Length == 0)
throw new Exception("队列为空,无法出队");
_pFront = (_pFront + 1) % MaxSize;
Length--;
}
/// <summary>
/// 判断队列是否为空
/// </summary>
/// <returns></returns>
public bool IsEmpty()
{
return Length == 0;
}
/// <summary>
/// 清空队列
/// </summary>
public void Clear()
{
_pFront = 0;
_pRear = 0;
Length = 0;
}
}