一、题目
题目:区间树查找算法
实验目的:实现有效的区间树查找算法
二、算法思想
1、基本概念:
区间:一个事件占用的时间
闭区间:实数的有序对[t1,t2],使t1≤t2
区间的对象表示:[t1,t2]可以用对象i表示,有两个属性:
low[i]=t1//起点或低点
high[i]=t2//终点或高点
区间的重叠:i∩i’≠Ø ⇔(low[i]≤high[i’]) and (low[i’]≤high[i])
2、数据结构:本质上是将红黑树扩充,方法如下:
Step 1:基本结构。以红黑树为基础,对∀x∈T,x包含区间int[x]的信息(低点和高点),key=low[int[x]]。
Step 2:附加信息。max[x]=max(high[int[x]], max[left[x]], max[right[x]])
Step 3:维护附加信息(有效性)。由定理14.1及max的定义⇒有效
Step 4:开发新操作。查找与给定区间重叠的区间keymax节点x
3、查找算法IntervalSearch(T, i)基本思想:
step 1:x ←root[T];//从根开始查找
step 2:若x≠nil[T]且i与int[x]不重叠
if x的左子树非空且左子树中最大高点≥low[i] then
x ←left[x];//到x的左子树中继续查找
else //左子树必查不到,到右子树查
x ←right[x];
step 3:返回x //x=nil or i和x重叠
由于区间树是红黑树的简单扩重,因此区间树相关操作的实现如左旋、右旋、插入,插入调整等与红黑树基本相同,具体而言,仅仅在左旋和右旋的操作中维护max域的取值正确即可,其他与红黑树操作完全相同。
本实验中构造的红黑树如下:
P187 图14-4
三、实验结果
四、结果分析
1、中序遍历的结果无误,表明区间树构造正确。
2、查找与区间[3,7]重叠的区间,打印的结果是中序遍历第二个那个节点,结果正确。
3、查找与区间[22,24]重叠的区间,打印的结果是null,表明未找到与此区间重叠的节点,结果正确。
4、查找与区间[21,21]重叠的区间,打印的结果是根节点,结果正确。
综上,本实验结果符合预期,正确无误,实现了有效的区间树查找算法。
五、总结
- 查找与i重叠的区间x的过程是现以x为树根开始,逐步下降。当找到一个重叠区域或x指向了nil[T]时,该过程结束。因为基本循环的每次迭代要花O(1)时间,又含n个节点的红黑树的高度为O(lg n),所以区间树查找算法的时间为O(lg n)。
- 先建树,然后插入数据,然后更新,查询。
附件:
源程序:IntervalTreeExperiment.java
/**
* @author
* Email:
* 创建时间:2012-11-16 下午6:44:52
* 类说明 :区间树查找算法
* @version
*/
public class IntervalTreeExperiment {
public static void main(String[] args) {
//构造如算法导论书本P187页图14-4的区间树
IntervalTree it = new IntervalTree();
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(16,21)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(8,9)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(25,30)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(5,8)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(15,23)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(17,19)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(26,26)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(0,3)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(6,10)));
IntervalTree.interval_insert(it,new IntervalTreeNode(new Section(19,20)));
System.out.println("中序遍历P187页图14-4的区间树:");
IntervalTree.inOrderTraverse(it.root);
//在此区间树中查找区间[3,7],并输出结果
System.out.println("在此区间树中查找区间[3,7]的结果:");
System.out.println(IntervalTree.interval_search(it, new Section(3,7)));
//在此区间树中查找区间[22,24],并输出结果
System.out.println("在此区间树中查找区间[22,24]的结果:");
System.out.println(IntervalTree.interval_search(it, new Section(22,24)));
//在此区间树中查找区间[21,21],并输出结果
System.out.println("在此区间树中查找区间[21,21]的结果:");
System.out.println(IntervalTree.interval_search(it, new Section(21,21)));
}
}
class IntervalTree {
public int number;
public IntervalTreeNode root;
public final static int RED=0;
public final static int BLACK=1;
public static boolean isOverlap(Section x, Section y){
return (x.high>=y.low) && (y.high>=x.low);
}
public static IntervalTreeNode interval_search(IntervalTree T,Section i){
//找出树T中覆盖区间i的那个节点
IntervalTreeNode x=T.root;
while(x!=null && !isOverlap(i, x.section)){
if((x.left != null) && (x.left.max >= i.low)){
x=x.left;
}
else{
x=x.right;
}
}
return x;
}
public static void left_rotate(IntervalTree it,IntervalTreeNode x) {//对x节点左旋转
if((it==null) || (x==null))return;
//set y
IntervalTreeNode y = x.right;
//turn y's left subtree into x's right subtree
x.right = y.left;
if(y.left != null) {
y.left.p = x;
}
//link x's parent to y
y.p=x.p;
if(x.p == null) {
it.root = y;
}
else if(x == x.p.left){
x.p.left=y;
}
else {
x.p.right=y;
}
//put x on y's left
y.left=x;
x.p=y;
//update max
x.max=Math.max(x.section.high, Math.max(x.left.max,x.right.max));
y.max=Math.max(y.section.high, Math.max(y.left.max,y.right.max));
}
public static void right_rotate(IntervalTree it,IntervalTreeNode y) {//对y节点右旋转
if((it==null) || (y==null))return;
//set x
IntervalTreeNode x = y.left;
//turn x's right subtree into y's left subtree
y.left=x.right;
if(x.right != null) {
x.right.p = y;
}
//link y's parent to x
x.p=y.p;
if(y.p == null) {
it.root = x;
}
else if(y == y.p.left){
y.p.left=x;
}
else {
y.p.right=x;
}
//put y on x's right
x.right=y;
y.p=x;
//update max
x.max=Math.max(x.section.high, Math.max(x.left.max,x.right.max));
y.max=Math.max(y.section.high, Math.max(y.left.max,y.right.max));
}
public static void interval_insert(IntervalTree it,IntervalTreeNode z){//在rb中插入z节点
if(z==null)return;
IntervalTreeNode y=null;
IntervalTreeNode x=it.root;
while(x != null) {
y=x;
if(z.key < x.key) {
x=x.left;
}
else {
x=x.right;
}
}
z.p=y;
if(y == null) {
it.root=z;
}
else if(z.key < y.key) {
y.left=z;
}
else {
y.right=z;
}
z.left=null;
z.right=null;
z.color=RED;
it.number++;
rb_insert_fixup(it,z);
}
public static void rb_insert_fixup(IntervalTree it,IntervalTreeNode z) {//调整插入后的树
while((z.p != null) && (z.p.color == RED)){
if((z.p.p != null) && (z.p == z.p.p.left)) { //父亲节点是祖先节点的左孩子
IntervalTreeNode y=z.p.p.right;//uncle y
if((y != null) && (y.color==RED)) {
z.p.color=BLACK;
y.color=BLACK;
z.p.p.color=RED;
z=z.p.p;//important
}
else {
if(z==z.p.right) {
z=z.p;
left_rotate(it,z);
}
z.p.color=BLACK;
z.p.p.color=RED;
right_rotate(it,z.p.p);
}
}
else if(z.p.p != null){//父亲节点是祖先节点的右孩子
IntervalTreeNode y=z.p.p.left;//uncle y
if((y != null) && (y.color==RED)) {
z.p.color=BLACK;
y.color=BLACK;
z.p.p.color=RED;
z=z.p.p;//important
}
else {
if(z==z.p.left) {
z=z.p;
right_rotate(it,z);
}
z.p.color=BLACK;
z.p.p.color=RED;
left_rotate(it,z.p.p);
}
}
}
it.root.color=BLACK;
}
// public static void interval_delete(IntervalTree T,IntervalTreeNode x){}
public static void inOrderTraverse(IntervalTreeNode root) {
if(root==null)return;
inOrderTraverse(root.left);
if(root.color==RBTree.BLACK) {
System.out.println(root.section+"\tblack\tmax="+root.max);
}
else {
System.out.println(root.section+"\tred\tmax="+root.max);
}
inOrderTraverse(root.right);
}
}
class IntervalTreeNode {
public IntervalTreeNode p;
public IntervalTreeNode left;
public IntervalTreeNode right;
public int key;
public int color;
//扩展红黑树
public Section section;
public int max;
public IntervalTreeNode(int key){
this.key=key;
}
public IntervalTreeNode(Section section) {
this.section=section;
key=section.low; // initialize key
max=section.high;// initialize max
}
@Override
public String toString() {
String color_str;
if(color==0){
color_str="red";
}
else{
color_str="black";
}
if(p!=null){
return "IntervalTreeNode [p=" + p.section + ", left=" + left.section + ", right="
+ right.section + ", color=" + color_str + ", section="
+ section + ", max=" + max + "]";
}
else{
return "IntervalTreeRootNode[left=" + left.section + ", right="
+ right.section + ", color=" + color_str + ", section="
+ section + ", max=" + max + "]";
}
}
}
class Section{
public int low;
public int high;
public Section(int low, int high) {
this.low = low;
this.high = high;
}
@Override
public String toString() {
return "[" + low + "," + high + "]";
}
}