Đây không phải là câu trả lời chính xác cho câu hỏi của bạn, nhưng tôi có một lớp giúp tăng hiệu suất của Contains () trên một tập hợp. Tôi xếp lớp con một Hàng đợi và thêm một Từ điển ánh xạ mã băm vào danh sách các đối tượng. Các Dictionary.Contains()
chức năng là O (1) trong khi List.Contains()
, Queue.Contains()
và Stack.Contains()
là O (n).
Kiểu giá trị của từ điển là một hàng đợi chứa các đối tượng có cùng một mã băm. Người gọi có thể cung cấp một đối tượng lớp tùy chỉnh triển khai IEqualityComparer. Bạn có thể sử dụng mẫu này cho Ngăn xếp hoặc Danh sách. Mã sẽ chỉ cần một vài thay đổi.
private class HashQueue<T> : Queue<T>
{
private readonly IEqualityComparer<T> _comp;
public readonly Dictionary<int, Queue<T>> _hashes;
public HashQueue(IEqualityComparer<T> comp = null) : base()
{
this._comp = comp;
this._hashes = new Dictionary<int, Queue<T>>();
}
public HashQueue(int capacity, IEqualityComparer<T> comp = null) : base(capacity)
{
this._comp = comp;
this._hashes = new Dictionary<int, Queue<T>>(capacity);
}
public HashQueue(IEnumerable<T> collection, IEqualityComparer<T> comp = null) : base(collection)
{
this._comp = comp;
this._hashes = new Dictionary<int, Queue<T>>(base.Count);
foreach (var item in collection)
{
this.EnqueueDictionary(item);
}
}
public new void Enqueue(T item)
{
base.Enqueue(item);
this.EnqueueDictionary(item);
}
private void EnqueueDictionary(T item)
{
int hash = this._comp == null ? item.GetHashCode() : this._comp.GetHashCode(item);
Queue<T> temp;
if (!this._hashes.TryGetValue(hash, out temp))
{
temp = new Queue<T>();
this._hashes.Add(hash, temp);
}
temp.Enqueue(item);
}
public new T Dequeue()
{
T result = base.Dequeue();
int hash = this._comp == null ? result.GetHashCode() : this._comp.GetHashCode(result);
Queue<T> temp;
if (this._hashes.TryGetValue(hash, out temp))
{
temp.Dequeue();
if (temp.Count == 0)
this._hashes.Remove(hash);
}
return result;
}
public new bool Contains(T item)
{
int hash = this._comp == null ? item.GetHashCode() : this._comp.GetHashCode(item);
return this._hashes.ContainsKey(hash);
}
public new void Clear()
{
foreach (var item in this._hashes.Values)
item.Clear();
this._hashes.Clear();
base.Clear();
}
}
Thử nghiệm đơn giản của tôi cho thấy rằng tôi HashQueue.Contains()
chạy nhanh hơn nhiều Queue.Contains()
. Chạy mã thử nghiệm với số đếm được đặt thành 10.000 mất 0.00045 giây đối với phiên bản HashQueue và 0.37 giây đối với phiên bản Hàng đợi. Với số lượng 100.000, phiên bản HashQueue mất 0,0031 giây trong khi Hàng đợi mất 36,38 giây!
Đây là mã thử nghiệm của tôi:
static void Main(string[] args)
{
int count = 10000;
{
var q = new HashQueue<int>(count);
for (int i = 0; i < count; i++)
q.Enqueue(i);
System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
bool contains = q.Contains(i);
}
sw.Stop();
Console.WriteLine(string.Format("HashQueue, {0}", sw.Elapsed));
}
{
var q = new Queue<int>(count);
for (int i = 0; i < count; i++)
q.Enqueue(i);
System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
bool contains = q.Contains(i);
}
sw.Stop();
Console.WriteLine(string.Format("Queue, {0}", sw.Elapsed));
}
Console.ReadLine();
}