二叉查找树,left < parent < right。比较简单。
AVL树,是平衡的二叉查找树。它是根据 rotate 操作来维持树的平衡的。
方便记忆一点,比如左旋 A ,就是 A 与 A 的右节点进行旋;右旋 B ,就是 B 与 B 的左节点进行旋。
那么,当 AVL 树不平衡时,就需要进行适当的 rotate 。具体应该有6种情况。由于对称性,只需要记忆3种。不妨设 x is right-heavy。
- y is right heavy. 那么左旋x。
- y is balanced. 那么左旋x。
- y is left-heavy. 那么右旋y,再左旋x。
Hash table,散列表、哈希表,其实都是一回事,根据key value直接访问元素的数据结构。Hash Function很重要。常见的Hash Function:http://blog.csdn.net/eaglex/article/details/6310727
处理碰撞有三种方法:
- 链接法。碰撞发生后,用链表将冲突元素链在原来元素后面。缺点是寻找元素时一定要把hash function指向的链表便利一遍。链接元素时,每个元素带有一个signature,不同元素对应的signature有小概率相同,先比较signature,再比较元素。
- open addressing。继续使用hash function找到下一个空位。
删除时,将此位标成删除位(tombstone)。以便跳转关系不被打乱,再有分配到此处时,可以overwrite,因此不会浪费空间。- linear probing,h(k i)=h’(k)+i。会形成簇,richer gets richer.
- double hashing, h(k,i) = f(k) + i·g(k) mod m。注意使g(k)与m互质,则可以覆盖所有的位置。
- 桶定址法。桶:一片足够大的地址空间。为表中每个元素分配一个桶。碰撞,桶不满继续加,桶满了使用开放地址法跳到下一个桶。
链接法与开放地址的比较:
- 开放地址节约空间(存储链表指针的空间)。
- 开放地址有更好的locality。
- 但开放地址需要好的哈希函数,以防止形成簇。
- 设a=n/m,存储元素占用空间/地址空间。a->1时,开放地址的碰撞跳转次数特别多,而且开放地址不可以令a>1。
滚动哈希 rolling hash 在字符串匹配中貌似有用。