数据结构之哈夫曼树、红黑树

来源:互联网 发布:android 与js交互 编辑:程序博客网 时间:2024/05/21 17:28

1、哈夫曼树又称为最优二叉树或带权路径长度最短的二叉树。其显著的特点是带权值的节点都是叶子节点,权值越小的节点,其到根节点的路径长度越长,反之,则越短。哈夫曼树可以有效的应用于压缩,我们可以把待压缩的文件中的字符的出现次数作为权值,权值越大的,距离根节点越近,字符编码越少。一般在节点左边的路径可用“0”表示,在节点右边的路径用“1”表示。详细可参照:http://blog.csdn.net/bruce_6/article/details/38656413

2、二叉树作为数据存储的工具具有重要的优势:可以快速地找到一个给定关键字的数据项,并且可以快速地插入和删除数据项。其他的数据存储结构,例如数组、有序数组以及链表,执行这些操作却很慢。因此,二叉树似乎是理想的数据存储结构。

遗憾的是,二叉搜索树有一个很麻烦的问题。如果树中插入的是随机数据,则执行效果很好。但是,如果插入的是有序的数据(17、21、28、36.....)或者逆序的数据(36,28,21,17,......),速度就变得特别慢。因为当前插入的数值有序时,二叉树就是非平衡的了。而对于非平衡树,它的快速查找(插入、删除)指定数据项的能力就丧失了。

解决非平衡树问题的方法:红-黑树,它是增加了某些特点的二叉搜索树,此外,还有2-3-4树,2-3树,外部存储等。

当树没有分支时(只有左子树或右子树的情况下),它其实就是一个链表。在这种情况下,查找的速度下降到O(N),而不是平衡树的O(logN)。对于随机数据的实际数量来说,一棵树特别不平衡的情况是不大可能的。但是,可能会有一部分有序数据使树部分非平衡。搜索部分非平衡树的时间介于O(N)~O(logN)之间,这取决于树的不平衡程度。

为了能以较快的时间O(logN)来搜索一棵树,需要保证树总是平衡的。红-黑树的平衡是在插入的过程中(删除时也是,但暂时忽略这个问题)取得的。对于一个要插入的数据项,插入例程要检查不会破坏树一定的特征。如果破坏了,程序就会进行纠正,根据需要更改树的结构。通过维持树的特征,保持了树的平衡。

红-黑树特征:

1、节点都是有颜色的;(颜色便于标记,在节点类中增加一个数据字段,可以是boolean型的(isRed),以此来表示颜色的信息)

2、在插入和删除的过程中,要遵循保持这些颜色的不同排列的规则;

红-黑规则:

(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

规则5的另一种陈述是所有从根到叶子节点路径上的黑色高度必须相同。所谓的黑色高度是指在从根到叶节点的路径上的黑色节点的数目。

如果存在重复关键字。则把有相同关键字的数据项分配到其他也有相同关键字数据项的两侧很重要。比如关键字的序列为50,50,50,要把第二个50放到第一个50的右边,并且把第三个50放到第一个50的左边。否则,树将不平衡。在插入算法中,用某种随机的过程处理相同关键字节点的分配问题。但是,如果要找到所有相同的关键字,插入过程就变得复杂了。因此不允许有关键字相同的数据项能使问题变得简单一些。

关于红黑树需要注意以下几点:

a)新插入的节点是红色的;

b)关于插入的处理:换色和旋转。具体如下:

如果叔叔节点是红色的,则换色;<换色>

如果叔叔节点是黑色,则细分为LL,LR,RR,RL四种情况;<旋转>

具体见:http://blog.csdn.net/xubaifu1997/article/details/52303872