实现了支持泛型的优先队列,解决Unity官方不提供优先队列的问题。
API
属性和字段 | 解释 |
---|
size | 队列的长度 |
capacity | 队列的容量 |
IsEmpty | 返回队列是否为空 |
Top | 返回队列第一个元素 |
枚举 | 解释 |
---|
PriorityQueueMode.less | 最小优先队列 |
PriorityQueueMode.equal | 只会将相等的排在一起 |
PriorityQueueMode.greator | 最大优先队列 |
函数 | 功能 |
---|
Push | 入队一个元素 |
Pop | 出队一个元素 |
Peek | 返回第一个元素 |
Clear | 清空队列 |
示例
PriorityQueue<int> priorityQueue = new PriorityQueue<int>((a, b) => {
if (a < b) return -1;
else if (a == b) return 0;
else if (a > b) return 1;
return 0;
});
priorityQueue.Push(8);
priorityQueue.Push(9);
priorityQueue.Push(3);
priorityQueue.Push(2);
priorityQueue.Push(7);
priorityQueue.Push(5);
priorityQueue.Push(0);
while (!priorityQueue.IsEmpty) {
Debug.Log(priorityQueue.Top);
priorityQueue.Pop();
}
实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace YBZ.Algorithm {
public class PriorityQueue<T> where T : new ()
{
public int size;
public int capacity;
private T[] elements;
public bool IsEmpty { get => size == 0; }
public T Top { get => elements[0]; }
private PriorityQueueMode _comparator;
public enum PriorityQueueMode {
less = -1,
equal = 0,
greater = 1
}
private Func<T,T,int> CMP;
public PriorityQueue(Func<T,T,int> CMP, PriorityQueueMode priorityQueueMode = PriorityQueueMode.less, int capacity = 1) {
this.CMP = CMP;
this.size = 0;
this.capacity = capacity;
this.elements = new T[capacity];
this._comparator = priorityQueueMode;
}
public void Push(T value) {
if (size == capacity) {
ExpandCapacity();
}
elements[size++] = value;
ShiftUp();
}
public void Pop() {
if(size == 0) {
return;
}
size--;
Swap(ref elements[0], ref elements[size]);
ShiftDown();
}
public void Clear() {
size = 0;
}
public T Peek() {
return Top;
}
private void ExpandCapacity() {
capacity = Mathf.CeilToInt(capacity * 1.5f);
T[] temp = new T[capacity];
for (int i = 0; i < elements.Length; i++) {
temp[i] = elements[i];
}
elements = temp;
}
private void ShiftUp() {
int cur = size - 1 ;
int parent = ( cur -1 ) >> 2;
while (cur > 0)
{
if (CMP(elements[cur],elements[parent]) == (int)_comparator) {
Swap(ref elements[cur], ref elements[parent]);
cur = parent;
parent = (cur - 1) >> 2;
} else break;
}
}
private void ShiftDown() {
int cur = 0;
int child = 1;
while (child < size) {
if (child + 1 < size && CMP(elements[child +1], elements[child]) == (int)_comparator) {
child++;
}
if (CMP(elements[child], elements[cur]) == (int)_comparator){
Swap(ref elements[child], ref elements[cur]);
cur = child;
child = cur << 1 + 1;
} else break;
}
}
private void Swap(ref T lhs,ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
public override string ToString() {
string result = "";
foreach (var v in elements) {
result += v.ToString();
}
return result;
}
}
}