|
1052 | 1052 | if(cmplo <= 0 && cmphi >= 0) queue.enqueue(node.k);
|
1053 | 1053 | if(cmphi > 0) keys(node.right, queue, lo, hi); //从当前结点开始向右遍历,直到接触到hi对应的结点,将所有之间的结点加入队列。[current-hi]
|
1054 | 1054 | }
|
| 1055 | + |
| 1056 | + ->性能分析: |
| 1057 | + 1.树的高度决定了树中和有序性相关的操作。 |
| 1058 | + 2.在一个二叉查找树中,所有操作在最坏情况下所需的时间和树的高度成正比。 |
| 1059 | + |
| 1060 | +6. 2-3查找树: |
| 1061 | + 2-结点:含有一个键和两条链接,类似于二叉树,左边链接的值小于键值,右边链接的键值大于键值。 |
| 1062 | + 2 |
| 1063 | + / \ |
| 1064 | + 1 3 |
| 1065 | + |
| 1066 | + 3-结点:含有两个键和三条链接,左边链接的键值小于左键值,中间链接的键值在左键值和右键值之间,右链接的键值大于右键值。 |
| 1067 | + 4 7 |
| 1068 | + / | \ |
| 1069 | + 1 2 5 8 9 |
| 1070 | + |
| 1071 | + ->查找结点get: |
| 1072 | + 通过比较键值递归查找,如果找到则返回该节点,直到遍历为空,退出循环,返回空值,说明没有该结点。 |
| 1073 | + ->放置结点put: |
| 1074 | + 添加新的结点之前需要通过get方法查找键,如果找到了,直接修改值,如果不为空,分为以下几种条件: |
| 1075 | + 1.向2-结点中添加新键。 |
| 1076 | + 2.向一个父结点为2-结点的3-结点添加新键。 |
| 1077 | + 3.向一个父结点为3-结点的3-结点添加新键:需要一直遍历到根节点判断是不是2-结点,其中有一个是2-结点,则归纳到1的情况。 |
| 1078 | + 分解根节点:如果根结点为一个4-结点,继续将中间的键向上移添加一个新的结点。 |
| 1079 | + |
| 1080 | +7. 红黑二叉查找树: |
| 1081 | + 1.红黑二叉查找树是一种2-3查找树的实现。 |
| 1082 | + 2.我们将树中的链接分为两种类型: |
| 1083 | + ->红链接:将两个2-结点连接起来构成一个3-结点。 |
| 1084 | + ->黑链接:2-3树中的普通链接。 |
| 1085 | + 3.替换3-结点: |
| 1086 | + 通过红链接将来通过二叉树来表示2-3链接。 |
| 1087 | + 将原来的3-结点转化成2-结点,并且将原来3-结点中的两个键通过红链接表示。 |
| 1088 | + 我们将这种方式表示的2-3树的二叉查找树成为红黑二叉查找树(红黑树)。 |
| 1089 | + ->红链接均为左链接。 |
| 1090 | + ->没有任何一个结点同时和两条红链接相连。 |
| 1091 | + ->该树是完美黑色平衡的,即任意空链接到根结点的路径上的黑链接数量相同。 |
| 1092 | + 实现:ca.mcmaster.chapter.three.rbtree.RedBlackBST<K, V> |
| 1093 | + public class RedBlackBST<K, V> { |
| 1094 | + private Node root; |
| 1095 | + public static final Boolean RED = true; |
| 1096 | + public static final Boolean BLACK = false; |
| 1097 | + private class Node{ |
| 1098 | + K k; |
| 1099 | + V v; |
| 1100 | + Node left, right; |
| 1101 | + int N; |
| 1102 | + Boolean color; |
| 1103 | + public Node(K k, V v, int n, Boolean color) { |
| 1104 | + this.k = k; |
| 1105 | + this.v = v; |
| 1106 | + N = n; |
| 1107 | + this.color = color; |
| 1108 | + } |
| 1109 | + } |
| 1110 | + |
| 1111 | + private Boolean isRed(Node node){ |
| 1112 | + if(null == node) return false; |
| 1113 | + return node.color == RED; |
| 1114 | + } |
| 1115 | + |
| 1116 | + public Node rotateLeft(Node node){ //将右侧的红链接与左链接(黑链接)交换 |
| 1117 | + Node temp = node.right; //思考:如果将原父结点作为temp需要4条赋值语句,所以通过将右结点作为中间变量可以减少开销。 |
| 1118 | + node.right = temp.left; |
| 1119 | + temp.left = node; |
| 1120 | + temp.color = node.color; |
| 1121 | + node.color = RED; |
| 1122 | + temp.N = node.N; |
| 1123 | + node.N = 1 + size(node.left) + size(node.right); |
| 1124 | + return temp; |
| 1125 | + } |
| 1126 | + public Node rotateRight(Node node){ //将左侧的红链接与右链接(黑链接)交换 |
| 1127 | + Node temp = node.left; |
| 1128 | + node.left = temp.right; |
| 1129 | + temp.right = node; |
| 1130 | + temp.color = node.color; |
| 1131 | + temp.N = size(node); |
| 1132 | + node.N = 1 + size(node.left) + size(node.right); |
| 1133 | + return temp; |
| 1134 | + } |
| 1135 | + public int size() { return size(root); } |
| 1136 | + public int size(Node node){ |
| 1137 | + if(null == node) return 0; |
| 1138 | + return node.N; |
| 1139 | + } |
| 1140 | + } |
| 1141 | + |
| 1142 | + 4.颜色转换: |
| 1143 | + ->两个子链接都是红链接,那么我们可以将父结点向上的链接变成红链接,将两个子链接变成黑链接。 |
| 1144 | + 实现:ca.mcmaster.chapter.three.rbtree.RedBlackBST#filpColor(Node) |
| 1145 | + ->根节点总是黑色的,根据上一条,我们总是会将根节点设置为红链接,但是我们要将父结点设置成黑链接,每次由红色变成黑色树的黑链接高度增加1. |
1055 | 1146 |
|
1056 | 1147 |
|
1057 | 1148 |
|
|
0 commit comments