一、算法的分析
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域的取值正确即可,其他与红黑树操作完全相同。
二、上机代码
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域的取值正确即可,其他与红黑树操作完全相同。
二、上机代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
enum NODECOLOR
{ BLACK =0,
RED =1
};
typedef struct INTERVALTree
{
struct INTERVALTree *parent;
struct INTERVALTree *left,*right;
int key;
int max;
int low;
int high;
NODECOLOR color;
}INTERVALTree, *PINTERVALTree;
void LEFT_ROTATE(PINTERVALTree x,PINTERVALTree root);
void RIGHT_ROTATE(PINTERVALTree x,PINTERVALTree root);
PINTERVALTree INTERVAL_INSERT(int key,int low,int high,PINTERVALTree root);
PINTERVALTree INTERVAL_INSERT_FIXUP(PINTERVALTree root,PINTERVALTree z);
PINTERVALTree INTERVAL_SEARCH(PINTERVALTree root,int low,int high);
void preorder_visit(PINTERVALTree t);
void print_node(PINTERVALTree node);
void LEFT_ROTATE(PINTERVALTree x,PINTERVALTree root)
{
PINTERVALTree y;
int i,j; /*用于存放原来x和y的max值*/
y=x->right;
i=x->max;
j=y->max;
x->right=y->left;
if(y->left!=NULL)
y->left->parent=x;
y->parent=x->parent;
if(x->parent==NULL)
root=y;
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
y->left=x;
x->parent=y;
if(x->high>j)
x->max=x->high;
else
x->max=j;
if(y->high>i)
y->max=y->high;
else
y->max=i;
}
void RIGHT_ROTATE(PINTERVALTree x,PINTERVALTree root)
{
PINTERVALTree y;
int i=0,j=0; /*用于存放原来x和y的max值*/
i=x->max;
j=y->max;
y=x->left;
x->left=y->right;
if(y->right!=NULL)
y->right->parent=x;
y->parent=x->parent;
if(x->parent==NULL)
root=y;
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
x->parent=y;
y->right=x;
if(x->high>j)
x->max=x->high;
else
x->max=j;
if(y->high>i)
y->max=y->high;
else
y->max=i;
}
PINTERVALTree INTERVAL_INSERT(int key,int low,int high,PINTERVALTree root)
{
PINTERVALTree x,y;
PINTERVALTree z;
z=(PINTERVALTree)malloc(sizeof(INTERVALTree));
z->key=key;
z->max=high;
z->low=low;
z->high=high;
y=NULL;
x=root;
while(x!=NULL)
{
y=x;
if(z->key<x->key)
x=x->left;
else
x=x->right;
}
z->parent=y;
if(y==NULL)
root=z;
else if(z->key<y->key)
y->left=z;
else
y->right=z;
z->left=z->right=NULL;
z->color=RED;
return INTERVAL_INSERT_FIXUP(root,z);
}
PINTERVALTree INTERVAL_INSERT_FIXUP(PINTERVALTree root,PINTERVALTree z)
{
PINTERVALTree y,a;
a=z;
while(z!=root&&z->parent->color==RED)
{
if(z->parent==z->parent->parent->left)
{
y=z->parent->parent->right;
if(y->color==RED)
{
y->color=BLACK;
z->parent->color=BLACK;
z->parent->parent->color=RED;
z=z->parent->parent;
}
else
{
if(z==z->parent->right)
{
z=z->parent;
LEFT_ROTATE(z,root);
}
z->parent->color=BLACK;
z->parent->parent->color=RED;
RIGHT_ROTATE(z->parent->parent,root);
}
}
else
{
y=z->parent->parent->left;
if(y->color==RED)
{
z->parent->color=BLACK;
y->color=BLACK;
z->parent->parent->color=RED;
z=z->parent->parent;
}
else
{
if(z==z->parent->left)
{
z=z->parent;
RIGHT_ROTATE(z,root);
}
z->parent->color=BLACK;
z->parent->parent->color=RED;
LEFT_ROTATE(z->parent->parent,root);
}
}
}
while(a->parent!=NULL&&a->parent->max<a->max)
{
a->parent->max=a->max;
a=a->parent;
}
root->color=BLACK;
return root;
}
PINTERVALTree INTERVAL_SEARCH(PINTERVALTree root,int low,int high)
{
PINTERVALTree x;
x=root;
while(x!=NULL&&(x->high < low || high < x->low))
{
if((x->left!=NULL)&&(x->left->max>=low))
x=x->left;
else
x=x->right;
}
return x;
}
void preorder_visit(PINTERVALTree t)
{
if(t!=NULL)
{
print_node(t);
if(t->left!=NULL)
preorder_visit(t->left);
if(t->right!=NULL)
preorder_visit(t->right);
}
}
void print_node(PINTERVALTree node)
{
char *color[]={"BLACK","RED"};
printf("%d %d %d %d %s ",node->key,node->max,node->low,node->high,color[node->color]);
}
int main()
{
PINTERVALTree root=NULL;
PINTERVALTree node;
int low,high;
char c1,c2,c3,c4;
char s1[7]="";
char s2[5]="exit";
char s3[5]="find";
char s4[7]="insert";
char s5[7]="";
while(strcmp(s1,s2)!=0)
{
printf("请输入输入相关实验数据,(exit/insert [xx,xx]):");
scanf("%s",s1);
if(strcmp(s1,s4)==0)
{
scanf("%c",&c1);
scanf("%c",&c2);
scanf("%d",&low);
scanf("%c",&c3);
scanf("%d",&high);
scanf("%c",&c4);
root=INTERVAL_INSERT(low,low,high,root);
}
else if(strcmp(s1,s2)==0)
break;
}
preorder_visit(root);
printf("\n");
printf("\n");
while(strcmp(s5,s2)!=0)
{
printf("请输入查找区间(find [xx,xx]):");
scanf("%s",s5);
if(strcmp(s5,s3)==0)
{
scanf("%c",&c1);
scanf("%c",&c2);
scanf("%d",&low);
scanf("%c",&c3);
scanf("%d",&high);
scanf("%c",&c4);
node=INTERVAL_SEARCH(root,low,high);
if(node!=NULL)
printf("\n区间[%d,%d]重叠的区间是:[%d,%d]\n",low,high,node->low,node->high);
else
printf("\n没有重叠的区间\n");
}
else if(strcmp(s5,s2)==0)
break;
}
return 0;
}