📅  最后修改于: 2023-12-03 14:39:45.386000             🧑  作者: Mango
哈希表是一个使用哈希函数来映射键值对的数据结构。而哈希链表则是一个使用链表来解决哈希冲突的哈希表。在C#中,可以通过使用泛型类Dictionary<TKey, TValue>来创建一个哈希表。这个类已经在内部实现了哈希链表,我们只需要提供键和值的类型就行了。
我们可以使用Dictionary<TKey, TValue>类来创建一个简单的哈希表。代码如下:
Dictionary<string, int> hashTable = new Dictionary<string, int>();
hashTable.Add("apple", 3);
hashTable.Add("banana", 5);
hashTable.Add("pear", 1);
在上面的代码中,我们创建了一个Dictionary<string, int>对象,它使用string作为键的类型,int作为值的类型。然后,我们使用Add方法向哈希表中添加了三个键值对。
我们可以使用哈希表中的键来查询它对应的值。代码如下:
int value = 0;
if (hashTable.TryGetValue("apple", out value))
{
Console.WriteLine("The value of apple is {0}", value);
}
else
{
Console.WriteLine("The apple is not found.");
}
在上面的代码中,我们使用TryGetValue方法来获取键为“apple”的值。这个方法将会返回一个布尔值,表示哈希表中是否找到了这个键。如果找到了,它将会返回true,并将这个值赋给value变量。否则,它将会返回false,我们需要自己来处理这种情况。
我们也可以遍历哈希表中的所有键值对。代码如下:
foreach (KeyValuePair<string, int> pair in hashTable)
{
string key = pair.Key;
int value = pair.Value;
Console.WriteLine("The value of {0} is {1}", key, value);
}
在上面的代码中,我们使用foreach循环来遍历哈希表中的所有键值对。每次循环中,我们都可以使用pair.Key和pair.Value属性来分别获取当前键值对的键和值。
如果我们需要创建一个自定义的哈希表,我们可以实现一个泛型类HashTable<TKey, TValue>。我们需要提供两个类型参数,一个表示键的类型,另一个表示值的类型。代码如下:
public class HashTable<TKey, TValue>
{
private LinkedList<KeyValuePair<TKey, TValue>>[] buckets;
private const int defaultCapacity = 16;
private int count = 0;
public HashTable()
{
buckets = new LinkedList<KeyValuePair<TKey, TValue>>[defaultCapacity];
}
public HashTable(int capacity)
{
buckets = new LinkedList<KeyValuePair<TKey, TValue>>[capacity];
}
public int Count
{
get { return count; }
}
public TValue this[TKey key]
{
get
{
int bucketIndex = GetBucketIndex(key);
LinkedList<KeyValuePair<TKey, TValue>> bucket = buckets[bucketIndex];
if (bucket != null)
{
foreach (KeyValuePair<TKey, TValue> pair in bucket)
{
if (pair.Key.Equals(key))
{
return pair.Value;
}
}
}
throw new KeyNotFoundException();
}
set
{
int bucketIndex = GetBucketIndex(key);
if (buckets[bucketIndex] == null)
{
buckets[bucketIndex] = new LinkedList<KeyValuePair<TKey, TValue>>();
}
bool keyFound = false;
foreach (KeyValuePair<TKey, TValue> pair in buckets[bucketIndex])
{
if (pair.Key.Equals(key))
{
pair.Value = value;
keyFound = true;
break;
}
}
if (!keyFound)
{
LinkedListNode<KeyValuePair<TKey, TValue>> node = new LinkedListNode<KeyValuePair<TKey, TValue>>(new KeyValuePair<TKey, TValue>(key, value));
buckets[bucketIndex].AddLast(node);
count++;
}
}
}
private int GetBucketIndex(TKey key)
{
int hashcode = key.GetHashCode();
int bucketIndex = hashcode % buckets.Length;
return bucketIndex;
}
}
在上面的代码中,我们定义了一个HashTable<TKey, TValue>类,它包含了一个buckets数组和一个count变量。buckets数组用来存储我们的键值对,而count变量用来记录哈希表中有多少个键值对。
我们还实现了一个GetBucketIndex方法来计算一个键对应的桶的索引。这个方法将会使用键的哈希码来计算,然后取模来获得一个索引值。
在我们的HashTable<TKey, TValue>类中,我们还实现了一个this索引器,用来获取或设置指定键的值。在这个索引器中,我们使用GetBucketIndex方法来获取这个键对应的桶的索引。然后,我们使用buckets数组来获取这个桶。如果这个桶为空,则说明哈希表中没有这个键。如果这个桶不为空,则说明哈希表中可能存在这个键。我们遍历这个桶中的所有键值对,看看是否存在对应的键。如果存在,则返回对应的值。如果不存在,则抛出一个KeyNotFoundException异常。
如果我们设置了一个不存在的键,我们首先需要通过GetBucketIndex方法来获取对应的桶的索引。然后,我们需要检查这个桶是否为空。如果这个桶为空,我们需要创建一个新的链表,并将其放到这个桶中。然后,我们遍历这个桶中的所有键值对,看看是否存在对应的键。如果存在,则使用新的值来替换旧的值。如果不存在,则将这个键值对添加到这个链表中,并将count加一。
哈希表链表是一个非常常用的数据结构,它可以用来高效地存储大量的键值对。在C#中,我们可以使用泛型类Dictionary<TKey, TValue>来创建一个哈希表,也可以通过实现HashTable<TKey, TValue>类来创建一个自定义的哈希表。无论我们使用哪种方法,我们都需要知道如何遍历哈希表中的所有键值对,以及如何获取或设置指定键的值。