区间树查找

一、算法的分析
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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fullstack_lth

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值