2009-03-09 11 views
28

Zdaję sobie sprawę, że C# i .NET w ogóle ma już klasy Hashtable i Dictionary.Jaki jest przykład implementacji Hashtable w języku C#?

Czy ktoś może wykazać w języku C# implementację HashTable?

Aktualizacja: W celu wyjaśnienia, nie jestem ncessarily szuka pełnej realizacji, tylko przykład podstawowe funkcje hashtable (tj dodawać, usuwać znaleźć przez klucz).

+0

Wiem, że to stare pytanie, ale ja naprawdę zadałem sobie trud wdrożenia prostego HashTable w 62 liniach kodu, który robi Add and Find. – RichardOD

+3

w 2015 można go znaleźć [tutaj] (http://referencesource.microsoft.com/#mscorlib/system/collections/hashtable.cs) –

+0

@mt_serg: niesamowita lektura. Dzięki za wskazanie tego. –

Odpowiedz

8

Czy obejrzałeś C5 collections? Możesz download the source, który zawiera tabelę mieszającą.

+0

Dzięki za link. Miałem nadzieję na mały podstawowy przykład Add/Remove z hashing modulo w tym, ale nie jestem pewien, czy to będzie wypełniać całą stronę –

2

Można zobaczyć proste „rosną tylko” hashtable here, co powinno dać wyobrażenie prostej implementacji.

Zastrzeżenie: Jest prawdopodobnie kilka błędów w kodzie, ale zasada jest taka sama :)

94

Długo po pytanie zostało zadane, więc nie należy się spodziewać, aby zarobić dużo rep. Jednak zdecydowałem, że byłoby fajnie napisać własny bardzo prosty przykład (w czasie krótszym niż 90 linii kodu):

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; 
     } 
    } 

Oto mała aplikacja Test:

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(); 
     } 

To nie jest najlepsza realizacja, ale działa dla Dodaj, Usuń i Znajdź. Używa on chaining i prostego algorytmu modulo do znalezienia odpowiedniego zasobnika.

+1

Jestem świadomy, że to pytanie i odpowiedź są dość stare, ale przyjmę ten długotrwały. Czy nie należy wstawiać \ delete \ find operacji o efektywności (O)? – vondip

+3

nie ..find jest tylko O ​​(n) najgorszym przypadkiem (wszystkie klucze mieszają się z tą samą wartością ... nie bardzo prawdopodobne hehe), ale spodziewany przypadek jest stały. Wstawianie i usuwanie są stałe, ponieważ właśnie tworzysz hasz i wstawiasz/usuwasz go z tego indeksu w tablicy. Nie ma tu iteracji nad elementami. – alexD

+2

Na pewno można spojrzeć na rzeczywiste implementacje kolekcji opartych na Hash, ale ten przykład jest czysty i doskonały do ​​zrozumienia algorytmu. Podkreśla użycie metod GetHashCode i Equals, co jest bardzo ważne dla uchwycenia mechaniki HashMap. Wielkie dzięki za tę odpowiedź. –