算法导论14.3 -区间树

来源:互联网 发布:淘宝网会员费 编辑:程序博客网 时间:2024/05/17 08:32

区间树是在红黑树的基础上拓展而来的数据结构,由于基础的存储数据不同。与数据相关的操作也会不同,比如红黑树中的节点之间如何比较大小的操作。以及由比较操作的改变而带来的插入,查找,删除操作的改变。为了同时支持书中的例子和所有的练习题,数据结构中占用的空间会稍大,但是这样的数据结构无法支持练习题14.3-7,所以先把14.3-7排除在外。为此我还是使用c语言(而不使用c++ template的原因是没必要做成模板,因为真正使用的数据结构往往要远复杂与这样简单的习题,模板做的不好也无济于事)。

代码稍微多了点,主要是测试比较麻烦。代码就放在一起了。经过测试百万个随机生成的区间的插入和删除目前没有出现问题。十万节点的3种搜索操作目前都未发现问题。

#include <stdio.h>#include <malloc.h>#include <stdlib.h>#include <time.h>#include <memory.h>#include <malloc.h>#include <limits.h>#define BLACK 1#define RED   0typedef struct Key {int start;int end;}KeyP;//ÓÃÓڱȽÏÁ½¸ö¼üÖµµÄ´óС£¬a>b   1//  a = b 0//  a<b  -1int ICmp(Key *a, Key *b){if (a->start > b->start) {return 1;}else if (a->start < b->start) {return -1;}else {if (a->end > b->end) {return 1;}else if (a->end < b->end) {return -1;}return 0;}return 0;}//·µ»ØÊÇ·ña£¬bÖ®¼ä´æÔÚ¸²¸Ç¹Øϵint Interval_overlap(struct Key *a, struct Key *b) {if (a->end < b->start || a->start > b->end)return 0;else return 1;}typedef struct node {struct node *left;struct node *right;struct node *parent;int color;Key data;int min_gap;int max;} *IBST_NODE;void init_Interval_tree(IBST_NODE T){T->left = T->right = T;T->parent = T;T->color = BLACK;T->data.end = INT_MAX;T->data.start = INT_MIN;T->min_gap = INT_MAX;T->max = INT_MIN;}IBST_NODE interval_search(IBST_NODE T, Key *i){IBST_NODE x = T->left;while (x != T&&Interval_overlap(i, &x->data) == 0) {if (x->left != T&&x->left->max >= i->start){x = x->left;}elsex = x->right;}//if(x == T)//return 0;return x;}IBST_NODE interval_search_min(IBST_NODE T, Key *i){IBST_NODE x = T->left;IBST_NODE pre = T;while (x != T){if (Interval_overlap(i, &x->data) == 1) {pre = x;if (x->left->max >= i->start) {x = x->left;}elsex = T;}else {if (x->left != T&&x->left->max >= i->start) {x = x->left;}else {x = x->right;}}}return pre;}static int G_SIZE;static int num_called;void iph_search(IBST_NODE T, Key *in, IBST_NODE x, IBST_NODE*vec){//in this function ALL the node in the x's subtree is less than interval in//the persistent condition iph_search can hold:// all the elem y in subtree x have : y->data->start < in->start //and x->max >= in->start;if (x != T){if (x->data.start >= in->start) {puts("something error iph_search x->start >= in->start");}if (x->data.end >= in->start) {vec[G_SIZE++] = x;}if (x->left->max >= in->start)iph_search(T, in, x->left, vec);if (x->right->max >= in->start)iph_search(T, in, x->right, vec);}}void iph_interval_search_all(IBST_NODE T, Key *in, IBST_NODE x, IBST_NODE *vec){if (x != T&&x->max >= in->start){num_called++;if (x->data.start >= in->start) {if (x->data.start <= in->end) {//this condition means that the node x's start pos is in the interval in;//x->data->start belongs to [in->start,in->end]//this condition we should add x to the result vector //and for x->left call this function again//for x->right call this function again vec[G_SIZE++] = x;//if(x->left->max >= in->start)iph_interval_search_all(T, in, x->left, vec);//if(x->right->max >= in->start)iph_interval_search_all(T, in, x->right, vec);}else {//in this condition we have that x is not in the interval in and x is totally greater than interval in;//so we should ignore the x->right subtree;//if(x->left->max >= in->start)iph_interval_search_all(T, in, x->left, vec);}}else {if(Interval_overlap(&x->data,in) == 1){vec[G_SIZE++] = x;}if (x->left->max >= in->start)iph_search(T, in, x->left, vec);iph_interval_search_all(T, in, x->right, vec);/*abandoned//in this case we have all the elem in x's left subtree is less than the interval inif(Interval_overlap(in,x->data) == 1){vec[G_SIZE++] = x;}//if(x->left->max >= in->start)iph_interval_search_all(T,in,x->left,vec);//if(x->right->max >= in->start)iph_interval_search_all(T,in,x->right,vec);*/}}}int interval_search_all(IBST_NODE T, Key *in, IBST_NODE **out){IBST_NODE  *vec = (IBST_NODE *)malloc(sizeof(IBST_NODE) * 100000);G_SIZE = 0;num_called = 0;iph_interval_search_all(T, in, T->left, vec);*out = vec;return G_SIZE;}IBST_NODE interval_search_exactly(IBST_NODE T, Key *in){IBST_NODE x = T->left;while (x != T) {switch (ICmp(&x->data, in)) {case 1:x = x->left;break;case -1:x = x->right;break;case 0:return x;}}return 0;}int mmax(int a, int b){return a > b ? a : b;}int mmin(int a, int b){return a < b ? a : b;}void maintain(IBST_NODE T, IBST_NODE x){if (x != T) {x->max = mmax(mmax(x->left->max, x->right->max), x->data.end);x->min_gap = mmin(mmin(x->left->min_gap, x->right->min_gap), x->data.end - x->data.start);}}void left_rotate(IBST_NODE T, IBST_NODE x){struct node * y = x->right;if (y == T) return;x->right = y->left;if (y->left != T) {y->left->parent = x;}y->left = x;y->parent = x->parent;if (x == y->parent->left) {y->parent->left = y;}else {y->parent->right = y;}x->parent = y;maintain(T, x);maintain(T, y);}void right_rotate(IBST_NODE T, IBST_NODE x){struct node *y = x->left;if (y == T) return;x->left = y->right;if (x->left != T) {x->left->parent = x;}y->right = x;y->parent = x->parent;if (x->parent->left == x) {x->parent->left = y;}else {x->parent->right = y;}x->parent = y;maintain(T, x);maintain(T, y);}void rb_insert_fixup(IBST_NODE T, IBST_NODE z){//printf("T->left->data = %d\n",T->left->data);IBST_NODE y;while (z->parent->color == RED){if (z->parent == z->parent->parent->left) {y = z->parent->parent->right;if (y->color == RED) {z = z->parent;maintain(T, z);z->color = BLACK;z = z->parent;maintain(T, z);z->color = RED;y->color = BLACK;}else {if (z == z->parent->right) {z = z->parent;left_rotate(T, z);}z->parent->color = BLACK;z->parent->parent->color = RED;right_rotate(T, z->parent->parent);z = z->parent->parent;break;}}else {y = z->parent->parent->left;if (y->color == RED) {z = z->parent;maintain(T, z);z->color = BLACK;z = z->parent;maintain(T, z);z->color = RED;y->color = BLACK;}else {if (z == z->parent->left) {z = z->parent;right_rotate(T, z);}z->parent->color = BLACK;z->parent->parent->color = RED;left_rotate(T, z->parent->parent);z = z->parent->parent;break;}}}T->left->color = BLACK;while (z != T) {maintain(T, z);z = z->parent;//puts("---");}}void rb_insert(IBST_NODE T, IBST_NODE z){IBST_NODE y = T;IBST_NODE x = T->left;while (x != T){y = x;if (ICmp(&z->data, &x->data) == -1)//if(z->data < x->data){x = x->left;}else {x = x->right;}}z->parent = y;if (y == T) {T->left = z;}else if (ICmp(&z->data , &y->data)  == -1) {y->left = z;}else {y->right = z;}z->left = T;z->right = T;z->color = RED;maintain(T, z);rb_insert_fixup(T, z);}IBST_NODE tree_minimum(IBST_NODE T, IBST_NODE x){IBST_NODE p = x;while (p->left != T) {p = p->left;}return p;}void rb_transplant(IBST_NODE T, IBST_NODE u, IBST_NODE v){if (u == u->parent->left) {u->parent->left = v;}else u->parent->right = v;v->parent = u->parent;}static int valid;int black_hight;int check(IBST_NODE T, IBST_NODE n){if (n == T) return 1;if (n == 0 || n->left == 0 || n->right == 0)return 0;if (n->color == RED) {if (n->left->color != BLACK || n->right->color != BLACK)return 0;}if (n->left == T || n->right == T) {int hight = 0;IBST_NODE p = n;while (p != T) {if (p->color == BLACK) {hight++;}p = p->parent;}if (valid) {if (black_hight != hight)return 0;}else {black_hight = hight;valid = 1;}//printf("black_hight = %d\n",hight);}if (n->left != T&&n->left->parent != n) {return 0;}if (n->right != T&&n->right->parent != n) {return 0;}if (!check(T, n->left) || !check(T, n->right))return 0;int max = n->max;int min = n->min_gap;maintain(T, n);if (n->max != max || n->min_gap != min) {puts("error found");n->max = max;n->min_gap = min;return 0;}return 1;}void rb_delete_fixup(IBST_NODE T, IBST_NODE x){IBST_NODE w;while (x != T->left && x->color == BLACK){if (x == x->parent->left){w = x->parent->right;if (w == T)puts("disaster 1");if (w->color == RED) {w->color = BLACK;if (x->parent->color != BLACK) {puts("x == x->parent->left x->parent->color!=BLACK");}x->parent->color = RED;left_rotate(T, x->parent);w = x->parent->right;}if (w->left->color == BLACK && w->right->color == BLACK){w->color = RED;x = x->parent;maintain(T, x);}else {if (w->right->color == BLACK) {//if(w->right == T){//puts("this should not happend w->right == T 1");//}if (w->left->color != RED) {puts("condition 3 error,w->left->color != RED 1");}w->left->color = BLACK;w->color = RED;right_rotate(T, w);w = x->parent->right;}if (w->right->color != RED) {puts("error in condition 4 w->right->color!=RED 1");}w->color = x->parent->color;x->parent->color = BLACK;w->right->color = BLACK;left_rotate(T, x->parent);///x = T->left;//x = w;x = x->parent;break;}}else {w = x->parent->left;if (w == T)puts("disaster 2");if (w->color == RED){w->color = BLACK;if (x->parent->color != BLACK) {puts("x == x->parent->right x->parent->color!=BLACK");}x->parent->color = RED;right_rotate(T, x->parent);w = x->parent->left;}if (w->left->color == BLACK&&w->right->color == BLACK) {//x->parent->color = BLACK;w->color = RED;x = x->parent;maintain(T, x);}else {if (w->left->color == BLACK) {//if(w->left == T){//puts("this should not happend w->right == T 3");//}if (w->right->color != RED) {puts("condition 3 error,w->left->color != RED 1");}w->right->color = BLACK;w->color = RED;left_rotate(T, w);w = x->parent->left;}if (w->left->color != RED) {puts("error in condition 4 w->right->color!=RED 2");}w->color = x->parent->color;x->parent->color = BLACK;w->left->color = BLACK;right_rotate(T, x->parent);///x = T->left;//x = w;x = x->parent;break;}}}//T->left->color = BLACK;x->color = BLACK;//if(x == T) x = T->parent;while (x != T) {maintain(T, x);x = x->parent;}}void rb_delete(IBST_NODE T, IBST_NODE z){if (z == T) {puts("cann't delete the tree");}IBST_NODE y = z;IBST_NODE x;int y_original_color = y->color;if (z->left == T){x = z->right;rb_transplant(T, z, x);}else if (z->right == T){x = z->left;rb_transplant(T, z, x);}else {y = tree_minimum(T, z->right);y_original_color = y->color;x = y->right;if (y->parent == z)x->parent = y;else {rb_transplant(T, y, y->right);y->right = z->right;y->right->parent = y;}rb_transplant(T, z, y);y->left = z->left;y->left->parent = y;y->color = z->color;}if (y_original_color == BLACK) {rb_delete_fixup(T, x);}else {if(x == T) x = x->parent;while (x != T) {maintain(T, x);x = x->parent;}}}void print(IBST_NODE T, IBST_NODE N){if (N != T) {printf("data = [%d,%d] color = %d max = %d min_gap = %d   ", N->data.start, N->data.end, N->color, N->max, N->min_gap);if (N->left != T)printf("N->left->data = [%d,%d]  ", N->left->data.start, N->left->data.end);if (N->right != T)printf("N->right->data = [%d,%d]  ", N->right->data.start, N->right->data.end);puts("");print(T, N->left);print(T, N->right);}}int cmp(const void * a,const void* b){return ICmp(&(*(IBST_NODE *)a)->data,&(*(IBST_NODE *)b)->data);}int main(){/**/struct  node tree;IBST_NODE T = &tree;init_Interval_tree(T);IBST_NODE *in = (IBST_NODE*)malloc(sizeof(struct node)*100000);srand((unsigned)time(0));//freopen(".//data1.txt","r",stdin);//freopen(".//out11.txt","w",stdout);for (int i = 0; i< 1000; i++){if(i%1000 == 0)printf("i= %d\n", i);in[i] = (IBST_NODE)malloc(sizeof(struct node));in[i]->data.start = rand() % 100000;in[i]->data.end = in[i]->data.start + rand() % 100000;if(in[i]->data.start > in[i]->data.end){puts("true error");return 0 ;}//scanf("%d%d",&in[i]->data.start,&in[i]->data.end);//printf("%d %d \n",in[i]->data.start,in[i]->data.end);//scanf("%d",&in[i]->data.start,&in[i]->data.end);//printf("%d ",in[i]->data);rb_insert(T, in[i]);//valid = 0;//if (!check(T, T->left))//printf(" i = %d something bed at [%d,%d] \n", i, in[i]->data.start, in[i]->data.end);//puts("-----------------------------------------------------------------");//if(i == 5000)//print(T,T->left);}//print(T, T->left);puts("--------------------------------------");valid = 0;if (!check(T, T->left))puts("error");/*struct Key temp;for (int i = 0; i < 10000; i++) {temp.start = rand() % 100000;temp.end = rand() % 100000;IBST_NODE re = interval_search(T, &temp);if (Interval_overlap(&re->data, &temp) == 0){puts("error in interval_search");return 0;}else {//puts("check");}}puts("----------------test1 success----------------------");*//*struct Key temp;for (int i = 0; i < 10000; i++) {temp.start = rand() % 100000;temp.end = temp.start + rand() % 100000;IBST_NODE re = interval_search_min(T, &temp);if (re!=0&&!Interval_overlap(&temp,&re->data)){puts("interval_search_min error 1");// ")printf("[%d,%d] something bed at [%d,%d] \n", temp.start, temp.end, re->data.start, re->data.end);break;}for (int i = 0; i < 100000; i++){if (Interval_overlap(&in[i]->data, &temp) && in[i] != re) {if (in[i]->data.start < re->data.start) {puts("interval_search_min error 2");// ")//return 0;}else if (in[i]->data.start == re->data.start &&(in[i]->data.end - in[i]->data.start) < (re->data.end - re->data.start)){puts("interval_search_min error 3");// ")//return 0;}}}}puts("----------------test2 success----------------------");struct Key temp;for (int i = 0; i < 10000; i++) {temp.start = rand() % 100000;temp.end = temp.start + rand() % 100000;IBST_NODE re = interval_search_exactly(T, &temp);if(re!= 0){if(re->data.start!=temp.start||re->data.end != temp.end){puts("error in interval_search_exactly");}}else{}}puts("----------------test3 success----------------------");*/struct  Key temp1;for (int i = 0; i < 1000; i++) {temp1.start = rand() % 100000;temp1.end = temp1.start + rand() % 100000;IBST_NODE *re;IBST_NODE *re1 = (IBST_NODE *)malloc(sizeof(IBST_NODE) * 100000);int size = interval_search_all(T,&temp1,&re);int size2 = 0;for(int i = 0;i<1000;i++){if(Interval_overlap(&temp1,&in[i]->data)==1){//size2++;re1[size2++] = in[i];}}if(size!=size2){puts("error 1 ");return 1;}qsort(re,size,sizeof(IBST_NODE),cmp);qsort(re1,size2,sizeof(IBST_NODE),cmp);for(int i = 0;i<size;i++){if(ICmp(&re[i]->data,&re1[i]->data)!=0){puts("error 2");return 0;}}puts("finish");free(re);free(re1);}/*for (int i = 0; i < 1000000; i++){if (i % 1000 == 0)printf("i= %d\n", i);//print(T, T->left);rb_delete(T, in[i]);if (i % 1000 == 0) {valid = 0;if (!check(T, T->left)) {printf(" i = %d  error at [%d,%d] \n", i, in[i]->data.start, in[i]->data.end);print(T, T->left);break;}}}*/getchar();return 0;}


原创粉丝点击