区间树查找

来源:互联网 发布:ios 无网络界面 编辑:程序博客网 时间:2024/05/14 16:19
一、算法的分析
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;}



0 0
原创粉丝点击