作为一个例子,我正在编写一个哈希表,其名称为键,电话号码为数据。它应该是一个与数字相结合的名称表(即结构表)还是只是数字表?因为如果你正在查找某人的电话号码,你已经知道了他们的姓名,所以我没有看到用这个号码存储名字的重点。
答案 0 :(得分:1)
对于您遇到的一些问题,有一些一般性的建议:
回到你的问题,HashTable是一个具有恒定时间访问权限的表实现。与地图一样,您可以在哈希表中存储键值对关联。但是,哈希表不按排序顺序存储数据。哈希表通过顶层的数组实现。每个密钥通过散列函数映射到数组中的一个槽。但有时将容器组合起来以获得每个容器的最佳优势是有用的。就像你的电话簿一样。
例如,假设我们想要根据多种密钥类型查找记录。
John-Romero
5673-67854
Alice-Nice
3452-878
我们希望能够通过输入他们的姓名或电话来查找记录。所以我们想要每个记录2个搜索键。 (我们假设所有密钥都是唯一的。)但是一张地图只允许我们每条记录只有一个密钥。一种解决方案是创建记录的主列表。对于每个键类型,创建一个包含指向电话簿中记录的迭代器的映射。
要进行记录插入O(1),列表将适用于电话簿。
想象一下拥有50,000个姓名/号码配对的电话簿。每个号码都是 10位数字。我们需要创建一个数据结构来查找名称 匹配特定的电话号码。理想情况下,名称查找应该是 O(1)时间预期,并且呼叫者ID系统应该使用O(n)存储器(n = 50,000)。
list<Record> phone_book;
要查看O(1),地图最适合按键。
map<string, list<Record>::iterator> names;
map<int, list<Record>::iterator> phones;
我们可以通过解除引用迭代器来打印记录:
cout << *names["John-Romero"];
这是一个带有单个密钥的Java示例程序
import java.util.*;
public class PhoneBook {
/**
* @param args the command line arguments.
*/
public static void main(String[] args) {
/* instantiate a Hashtable Object*/
Hashtable dict = new Hashtable();
/* it is just an iterator */
Enumeration iterator;
/* the temporary key value*/
String tempKey;
/* here we put some key and value */
dict.put("Zahurul Islam",new Long(898989));
dict.put("Naushad Uzzaman", new Long(676767));
dict.put("Asif Iqbal", new Long(565656));
dict.put("Mr.Pavel", new Long(232323));
dict.put("Marzy Rahman",new Long(343434));
dict.put("Mehedi Al mamun",new Long(234324));
/* here we traverse the dict */
iterator = dict.keys();
while (iterator.hasMoreElements()) {
Object key = iterator.nextElement();
System.out.println("Name: "+ key +" Phone Number: "+ dict.get(key));
}
/* this is temporay key, if this is exist we just change the value
* other wise we put the pair(key,value) */
tempKey = "Zahurul Islam";
if(!dict.containsKey(tempKey)) {
System.out.println("No such Name in this phone Book");
} else {
Long phoneNumber = (Long) dict.get(tempKey);
long phNum = phoneNumber.longValue();
System.out.println(phNum+ " This Phone Number of "+ tempKey + " is changed ");
dict.put(tempKey, new Long(121212));
}
System.out.println("\nUpdated Phone book\n");
iterator = dict.keys();
while (iterator.hasMoreElements()) {
Object key = iterator.nextElement();
System.out.println("Name: "+ key +" Phone Number: "+ dict.get(key));
}
}
}
这是其他的2键
import java.io.*;
import java.lang.reflect.Array;
import static java.lang.System.out;
import java.util.*;
/************************************************************************************
* This class provides hash maps that use the hashing with separate chaining algorithm.
* A hash table is created that is an array of buckets. It restricts the number of
* slots per bucket to one (just one key-value pair), but could easily be extended
* to support multiple key-value pairs per bucket.
*/
public class HashSC <K, V>
extends AbstractMap <K, V>
implements Serializable, Cloneable, Map <K, V>
{
/********************************************************************************
* This inner class defines buckets that are stored in the hash table.
*/
private class Bucket
{
K key; // alt. use K [] instead of K
V value; // alt. use V [] instead of V
Bucket next;
Bucket (K k, V v, Bucket n) { key = k; value = v; next = n; }
} // Bucket inner class
/** The array of buckets making up the hash table.
*/
private final Bucket [] hTable;
/** The size of the hash table (number of home buckets)
*/
private final int size;
/** Counter for the number buckets accessed (for performance testing)
*/
private int count = 0;
/********************************************************************************
* Construct a hash table that uses separate chaining.
* @param cap the capacity of the hash table
*/
@SuppressWarnings("unchecked")
public HashSC (int cap)
{
hTable = (Bucket []) Array.newInstance (Bucket.class, size = cap);
} // HashSC
/********************************************************************************
* Return a set view of map containing all the entries as pairs of keys and values.
* @return the set view of the map
*/
public Set <Map.Entry <K, V>> entrySet ()
{
Set <Map.Entry <K, V>> enSet = new HashSet <> ();
for (int i = 0; i < size; i++) {
for (Bucket b = hTable [i]; b != null; b = b.next) {
enSet.add (new AbstractMap.SimpleEntry <K, V> (b.key, b.value));
} // for
} // for
return enSet;
} // entrySet
/********************************************************************************
* Given the key, look up the value in the hash table.
* @param key the key used for look up
* @return the value associated with the key
*/
public V get (Object key)
{
int i = h (key);
for (Bucket b = hTable [i]; b != null; b = b.next) {
count++;
if (b.key.equals (key)) return b.value;
} // for
return null;
} // get
/********************************************************************************
* Put the key-value pair in the hash table.
* @param key the key to insert
* @param value the value to insert
* @return null (not the previous value)
*/
public V put (K key, V value)
{
int i = h (key);
hTable [i] = new Bucket (key, value, hTable [i]);
return null;
} // put
/********************************************************************************
* Return the size (number of home buckets) in the hash table.
* @return the size of the hash table
*/
public int size ()
{
return size;
} // size
/********************************************************************************
* Print the hash table.
*/
private void print ()
{
out.println ("Hash Table (hashing with separate chaining)");
out.println ("-------------------------------------------");
for (int i = 0; i < size; i++) {
out.print (i + ":\t");
boolean notFirst = false;
for (Bucket b = hTable [i]; b != null; b = b.next) {
if (notFirst) out.print ("--> ");
out.print ("[ " + b.key + " ]\t");
notFirst = true;
} // for
out.println ();
} // for
out.println ("-------------------------------------------");
} // print
/********************************************************************************
* Hash the key using the hash function.
* @param key the key to hash
* @return the location of the bucket chain containing the key-value pair
*/
private int h (Object key)
{
return key.hashCode () % size;
} // h
/********************************************************************************
* The main method used for testing.
* @param the command-line arguments (args [0] gives number of keys to insert)
*/
public static void main (String [] args)
{
HashSC <Integer, Integer> ht_i = new HashSC <> (11);
HashSC <String, Integer> ht_s = new HashSC <> (11);
int nKeys = 30;
if (args.length == 1) nKeys = Integer.valueOf (args [0]);
for (int i = 1; i < nKeys; i += 2) {
ht_i.put (i, i * i);
ht_s.put ("s" + i, i * i);
} // for
ht_i.print ();
ht_s.print ();
for (int i = 0; i < nKeys; i++) {
out.println ("key = " + i + " value = " + ht_i.get (i));
out.println ("key = s" + i + " value = " + ht_s.get ("s" + i));
} // for
out.println ("-------------------------------------------");
out.println ("Average number of buckets accessed = " + ht_i.count / (double) nKeys);
out.println ("Average number of buckets accessed = " + ht_s.count / (double) nKeys);
} // main
} // HashSC class
我认为您可以比较两种解决方案的效率(最后一段代码需要修改为电话簿),以便您可以决定哪种解决方案更适合您的需求。