2009-03-09 25 views
28

Mi rendo conto che C# e .NET in generale hanno già le classi Hashtable e Dictionary.Che cos'è un esempio di implementazione di Hashtable in C#?

Qualcuno può dimostrare in C# un'implementazione di un Hashtable?

Aggiornamento: Per chiarire, non sto ncessarily alla ricerca di una completa implementazione, solo un esempio delle caratteristiche fondamentali di una tabella hash (cioè aggiungere, rimuovere, trovare a chiave).

+0

So che è una vecchia domanda, ma in realtà mi sono preso la briga di implementare una semplice HashTable in 62 righe di codice che aggiunge e trova. – RichardOD

+3

nel 2015 puoi trovarlo [qui] (http://referencesource.microsoft.com/#mscorlib/system/collections/hashtable.cs) –

+0

@mt_serg: una lettura fantastica. Grazie per questo. –

risposta

8

Hai guardato il C5 collections? È possibile download the source che include una tabella hash.

+0

Grazie per il link. Speravo in un piccolo esempio di base di Aggiungi/Rimuovi con il modulo di hashing incluso, ma non sono sicuro se questo riempirà l'intera pagina –

2

È possibile visualizzare un semplice 'crescere solo' tabella hash here, che dovrebbe dare un'idea di una semplice implementazione.

Disclaimer: C'è probabilmente qualche bug nel codice, ma il principio è lo stesso :)

94

Molto tempo dopo la domanda è stato chiesto, quindi non mi aspetto di guadagnare molto rep. Comunque ho deciso che sarebbe stato divertente per scrivere il mio esempio molto semplice (in meno di 90 righe di codice):

public struct KeyValue<K, V> 
    { 
     public K Key { get; set; } 
     public V Value { get; set; } 
    } 

    public class FixedSizeGenericHashTable<K,V> 
    { 
     private readonly int size; 
     private readonly LinkedList<KeyValue<K,V>>[] items; 

     public FixedSizeGenericHashTable(int size) 
     { 
      this.size = size; 
      items = new LinkedList<KeyValue<K,V>>[size]; 
     } 

     protected int GetArrayPosition(K key) 
     { 
      int position = key.GetHashCode() % size; 
      return Math.Abs(position); 
     } 

     public V Find(K key) 
     { 
      int position = GetArrayPosition(key); 
      LinkedList<KeyValue<K, V>> linkedList = GetLinkedList(position); 
      foreach (KeyValue<K,V> item in linkedList) 
      { 
       if (item.Key.Equals(key)) 
       { 
        return item.Value; 
       } 
      } 

      return default(V); 
     } 

     public void Add(K key, V value) 
     { 
      int position = GetArrayPosition(key); 
      LinkedList<KeyValue<K, V>> linkedList = GetLinkedList(position); 
      KeyValue<K, V> item = new KeyValue<K, V>() { Key = key, Value = value }; 
      linkedList.AddLast(item); 
     } 

     public void Remove(K key) 
     { 
      int position = GetArrayPosition(key); 
      LinkedList<KeyValue<K, V>> linkedList = GetLinkedList(position); 
      bool itemFound = false; 
      KeyValue<K, V> foundItem = default(KeyValue<K, V>); 
      foreach (KeyValue<K,V> item in linkedList) 
      { 
       if (item.Key.Equals(key)) 
       { 
        itemFound = true; 
        foundItem = item; 
       } 
      } 

      if (itemFound) 
      { 
       linkedList.Remove(foundItem); 
      } 
     } 

     protected LinkedList<KeyValue<K, V>> GetLinkedList(int position) 
     { 
      LinkedList<KeyValue<K, V>> linkedList = items[position]; 
      if (linkedList == null) 
      { 
       linkedList = new LinkedList<KeyValue<K, V>>(); 
       items[position] = linkedList; 
      } 

      return linkedList; 
     } 
    } 

Ecco una piccola applicazione di prova:

static void Main(string[] args) 
     { 
      FixedSizeGenericHashTable<string, string> hash = new FixedSizeGenericHashTable<string, string>(20); 

      hash.Add("1", "item 1"); 
      hash.Add("2", "item 2"); 
      hash.Add("dsfdsdsd", "sadsadsadsad"); 

      string one = hash.Find("1"); 
      string two = hash.Find("2"); 
      string dsfdsdsd = hash.Find("dsfdsdsd"); 
      hash.Remove("1"); 
      Console.ReadLine(); 
     } 

Non è la migliore realizzazione, ma funziona per Aggiungi, Rimuovi e Trova. Utilizza chaining e un semplice algoritmo modulo per trovare il bucket appropriato.

+1

Sono consapevole che questa domanda e risposta sono piuttosto vecchie, ma prenderò questo risultato. Non dovrebbe inserire \ delete \ trovare operazioni essere di efficienza O (n)? – vondip

+3

no ..find è solo O (n) worst case (tutte le hash delle chiavi hanno lo stesso valore ... non molto probabile hehe), ma il caso previsto è costante. Insert e Delete sono entrambi costanti dal momento che basta creare l'hash e inserirlo/rimuoverlo da quell'indice dell'array..non c'è iterazione sugli elementi. – alexD

+2

Certo, puoi guardare alle implementazioni del mondo reale delle raccolte basate su hash, ma questo esempio è pulito e ottimo per capire l'algoritmo. Sottolinea l'uso dei metodi GetHashCode e Equals che è molto importante per comprendere i meccanismi di HashMap. Grazie mille per questa risposta. –