散列表详解

散列表是一种将键(key)映射为值(value)从而实现快速查找的数据结构。在简
易实现中,散列表包含一个底层数组和一个散列函数(hash function)。插入一
个对象及对应的键时,散列函数会将键映射为数组的一个索引。然后,这个对象就
会储存到数组中该索引对应的位置。

不过,通常情况下,这个方法还不够完善。在上面的实现中,所有可能的键必须转
化为各不相同的散列值,否则一不小心就可能改写某些数据。因此,为了防止这
类“碰撞冲突”,这个数组会变得非常大,以便放下所有可能的键。

除了创建按索引hash(key)储存对象的超大数组,我们还可以选用小得多的数组,
并将对象储存在索引为hash(key) % array_length的数组元素指向的链表中。要
通过某个键来查找对象,就必须根据散列值找到对应的链表,然后在链表中查找相
应的键。 

另外,我们还可以采用二叉查找树来实现散列表。只要我们让这棵树保持平衡,就
能保证数据查找用时为O(log n)。此外,这种实现占用的空间可能更少,原因很简
单,我们不必一开始就分配一个大数组。 

public HashMap buildMap(Student[] students) { 
    HashMap map = new HashMap ();  
    for (Student s : students) map.put(s.getId(), s); 
    return map;  
} 

2. ArrayList(动态数组)
ArrayList,即动态数组,是一种按需动态调整大小的数组,数据访问时间为O(1)。一种典型的实现是在数组存满时将其扩容两倍。每次扩容用时O(n),不过这种操作频次极少,因此均摊下来访问时间仍为O(1)。

public ArrayList merge(String[] words, String[] more) { 
    ArrayList sentence = new ArrayList (); 
    for (String w : words)sentence.add(w);
    for (String w : more) sentence.add(w);    
    return sentence;
}


3. StringBuffer
假设你要将一组字符串拼接起来,如下所示。这段代码会运行多长时间?为简单起见,假设所有字符串等长(皆为x),一共有n个字符串。

public String joinWords(String[] words) {
    String sentence =“”; 
    for (String w : words) {
    sentence = sentence + w;
    }
    return sentence;
}


每次拼接都会新建一个字符串,包含原有两个字符串的全部字符。第一次循环要拷贝x个字符,第二次循环要拷贝2x个字符,第三次要拷3x个,依此类推。综上,这段代码的时间开销为O(x + 2x + ... + nx),可简化为O(xn2)。为什么不是O(xnn)?因为1 + 2 + ... + n等于n(n+1)/2,即O(n2)StringBuffer可以避免上面的问题。它会直接创建一个足以容纳所有字符串的数
组,等到拼接完成才将这些字符串转成一个字符串。

public String joinWords(String[] words) {
    StringBuffer sentence= new StringBuffer(); 
    for (String w : words) {
    sentence.append(w); 
    } 
    return sentence.toString();
}


不妨试着自己实现一把StringBuffer,这对你掌握字符串、数组和常见数据结构大 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值