Ini bukanlah jawaban yang tepat untuk pertanyaan Anda, tetapi saya memiliki kelas yang meningkatkan kinerja Contains () pada sebuah koleksi. Saya membuat subclass Queue dan menambahkan Dictionary yang memetakan kode hash ke daftar objek. The Dictionary.Contains()
fungsi O (1) sedangkan List.Contains()
, Queue.Contains()
, dan Stack.Contains()
adalah O (n).
Tipe nilai kamus adalah antrian yang menampung objek dengan kode hash yang sama. Pemanggil dapat menyediakan objek kelas khusus yang mengimplementasikan IEqualityComparer. Anda dapat menggunakan pola ini untuk Tumpukan atau Daftar. Kode hanya perlu beberapa perubahan.
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();
}
}
Pengujian sederhana saya menunjukkan bahwa HashQueue.Contains()
lari saya jauh lebih cepat daripada Queue.Contains()
. Menjalankan kode tes dengan hitungan diatur ke 10.000 membutuhkan 0,00045 detik untuk versi HashQueue dan 0,37 detik untuk versi Antrian. Dengan hitungan 100.000, versi HashQueue membutuhkan 0,0031 detik sedangkan Antrian membutuhkan 36,38 detik!
Inilah kode pengujian saya:
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();
}