标签:2-3树
这几天学习和实现了《数据结构(c语言版)》(李建中等人翻译的那本)里介绍的2-3树!
说实在,我若过一段时间来看这里的代码,估计我也看不懂了,不过结合书和书里的笔记,我想我还看得懂。
对以下代码有兴趣的学者,应该结合那本书来看吧!!!
大概说下:
插入:
a:待插入点,是2节点的,就往这里插入即可。
b: 待插入点,是3节点的,拆分这个节点。(小值留下,中值待定,大值放入新节点)。同时还得分这个被split的节点是左中右节点来分别处理。
删除:
....看书吧,情况分为7种或8种........
#include <stdio.h> #include <limits.h> #include <stdlib.h> //INT_MAX #define NODE_SIZE 100 typedef struct two_three *two_three_ptr; typedef int element; struct two_three{ element data_l,data_r; two_three_ptr left_child,middle_child,right_child; }; two_three_ptr node[NODE_SIZE];//for insert int nodetop=0; two_three_ptr nodedel[NODE_SIZE];//for delete int nodedeltop=0; int compare(two_three_ptr t,element x); void pushnode(two_three_ptr t,two_three_ptr *n,int *top); two_three_ptr popnode(two_three_ptr *n,int *top); two_three_ptr search23(two_three_ptr t,element x);//search void insert23(two_three_ptr *t,element y);//insert void new_root(two_three_ptr *t,element y,two_three_ptr q);//新的根节点 two_three_ptr find_node(two_three_ptr t,element y,two_three_ptr *n,int *top);//关键字在否 void put_in(two_three_ptr p,element y,two_three_ptr q); void split(two_three_ptr p,element *y,two_three_ptr *q); void delete23(two_three_ptr *t,element y);//delete two_three_ptr change(two_three_ptr d,element y);//交换节点 void deleteleaf(two_three_ptr *t,two_three_ptr d,element y);//删除叶子d节点上的y元素 void deleteone(two_three_ptr *t,two_three_ptr d); void a_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s); void b_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s); void c_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s); void a_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s); void b_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s); void c_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s); void d_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s); void e_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s); two_three_ptr search23(two_three_ptr t,element x)//search { int i=0; while(t) { ++i; switch( compare(t,x) ) { case 1:t=t->left_child;break; case 2:t=t->middle_child;break; case 3:t=t->right_child;break; case 4:{printf("%d层",i); return t;} default: fprintf(stderr,"have a error in search23\n"); } } return NULL; } void insert23(two_three_ptr *t,element y)//insert {//y是元素, p是栈上的节点,q是新节点 two_three_ptr q,p; if( !(*t) )//tree is empty new_root(t,y,NULL); else{ p=find_node(*t,y,node,&nodetop);//关键字在否 if(!p) { fprintf(stderr,"the key is currently in the tree\n"); exit(1); } q=NULL; while(1) { if(p->data_r == INT_MAX) {//2 node put_in(p,y,q); break; } else{ split(p,&y,&q); if(p == *t) {//split the root new_root(t,y,q); break; } else p=popnode(node,&nodetop);//remote a node from stack } } } } int compare(two_three_ptr t,element x)//查找元素在哪里 { if (x < t->data_l) return 1; else if(x == t->data_l) return 4; else if(x > t->data_l && x < t->data_r) return 2; else if(x == t->data_r) return 4; else if(x > t->data_r) return 3; return 0; } void new_root(two_three_ptr *t,element y,two_three_ptr q)//新的根节点 { two_three_ptr n=(two_three_ptr)calloc(1,sizeof(two_three)); n->data_l=y; n->data_r=INT_MAX; n->left_child=*t; n->middle_child=q; n->right_child=NULL; *t=n; } two_three_ptr find_node(two_three_ptr t,element y,two_three_ptr *n,int *top)//关键字在否 { while(t) { pushnode(t,n,top); switch( compare(t,y) ) { case 1:t=t->left_child;break; case 2:t=t->middle_child;break; case 3:t=t->right_child;break; case 4:return NULL;//有这个关键字了,返回NULL } } return n[--(*top)];//返回关键字应该插入的地方 } void put_in(two_three_ptr p,element y,two_three_ptr q) { if (y < p->data_l) { p->right_child=p->middle_child; p->middle_child=q; p->data_r=p->data_l; p->data_l=y; } else //y>p->data_l { p->data_r=y; p->right_child=q; } } void split(two_three_ptr p,element *y,two_three_ptr *q) { //分为 小值(左孩子过来),中值(中孩子过来的),大值(右孩子过来的) element temp; two_three_ptr n=(two_three_ptr)calloc(1,sizeof(two_three)); if (*y < p->data_l)//小值(左孩子过来), { n->data_l=p->data_r; n->left_child=p->middle_child; n->middle_child=p->right_child; temp=p->data_l; p->data_l=*y; p->middle_child=*q; *y=temp; } else if (*y > p->data_l && *y < p->data_r)//中值(中孩子过来的) { n->data_l=p->data_r; n->left_child=*q; n->middle_child=p->right_child; } else if (*y > p->data_r)//大值(右孩子过来的) { n->data_l=*y; n->left_child=p->right_child; n->middle_child=*q; *y=p->data_r; } *q=n; p->data_r=INT_MAX; p->right_child=NULL; n->data_r=INT_MAX; } void pushnode(two_three_ptr t,two_three_ptr *n,int *top) { if (*top == NODE_SIZE) { printf("error :nodetop is too high"); } n[(*top)++]=t;//++的优先级高于 * ;这里一开始错了我 } two_three_ptr popnode(two_three_ptr *n,int *top) { if (*top == 0) { printf("error :nodetop is less zero"); } return n[--(*top)]; } void delete23(two_three_ptr *t,element y)//delete { two_three_ptr temp; if(find_node(*t,y,nodedel,&nodedeltop) == NULL) {//存在 temp=popnode(nodedel,&nodedeltop); if (temp->left_child == NULL){//是叶子节点 deleteleaf(t,temp,y); } else{//非叶子节点,这里找左子树的最大值来做替换 pushnode(temp,nodedel,&nodedeltop); temp=change(temp,y); deleteleaf(t,temp,y); } } else{//不存在 printf("element is not exist\n"); } } void deleteleaf(two_three_ptr *t,two_three_ptr d,element y)//删除叶子d节点上的y元素 { if (d->data_r == y)//两个值的最右值 { d->data_r=INT_MAX; } else if (d->data_l == y && d->data_r !=INT_MAX )//两个值的最左值 { d->data_l=d->data_r; d->data_r=INT_MAX; } else//一个节点的,删除后要旋转或合并,大头啊!!! { deleteone(t,d); } } void deleteone(two_three_ptr *t,two_three_ptr d) { d->data_l=INT_MAX; while(d->data_l == INT_MAX) { if (d == *t) { *t=d->left_child; break; } two_three_ptr parent=popnode(nodedel,&nodedeltop); if (parent->left_child==d && parent->middle_child->data_r != INT_MAX)//a旋转 a_rotate(t,parent,d); else if (parent->middle_child==d && parent->left_child->data_r != INT_MAX)//b旋转 b_rotate(t,parent,d); else if (parent->right_child==d && parent->middle_child->data_r != INT_MAX)//c旋转 c_rotate(t,parent,d); else if (parent->left_child==d && parent->data_r == INT_MAX && parent->middle_child->data_r == INT_MAX)//a合并 a_merge(t,parent,d); else if (parent->left_child==d && parent->data_r != INT_MAX && parent->middle_child->data_r == INT_MAX)//b合并 b_merge(t,parent,d); else if (parent->middle_child==d && parent->data_r == INT_MAX && parent->left_child->data_r == INT_MAX)//c合并 c_merge(t,parent,d); else if (parent->middle_child==d && parent->data_r != INT_MAX && parent->left_child->data_r == INT_MAX)//d合并 d_merge(t,parent,d); else if (parent->right_child==d && parent->middle_child->data_r == INT_MAX)//e合并 e_merge(t,parent,d); d=parent; } } void a_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { s->data_l=p->data_l; p->data_l=p->middle_child->data_l; p->middle_child->data_l=p->middle_child->data_r; p->middle_child->data_r=INT_MAX; s->middle_child=p->middle_child->left_child; p->middle_child->left_child=p->middle_child->middle_child; p->middle_child->middle_child=p->middle_child->right_child; p->middle_child->right_child=NULL; } void b_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { s->data_l=p->data_l; p->data_l=p->left_child->data_r; p->left_child->data_r=INT_MAX; s->middle_child=s->left_child; s->left_child=p->left_child->right_child; p->left_child->right_child=NULL; } void c_rotate(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { s->data_l=p->data_r; p->data_r=p->middle_child->data_r; p->middle_child->data_r=INT_MAX; } void a_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { s->data_l=p->data_l; s->data_r=p->middle_child->data_l; p->data_l=INT_MAX; s->middle_child=p->middle_child->left_child; s->right_child=p->middle_child->middle_child; free(p->middle_child); p->middle_child=NULL; } void b_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { s->data_l=p->data_l; s->data_r=p->middle_child->data_l; p->data_l=p->data_r; p->data_r=INT_MAX; s->middle_child=p->middle_child->left_child; s->right_child=p->middle_child->middle_child; free(p->middle_child); p->middle_child=p->right_child; p->right_child=NULL; } void c_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { p->left_child->data_r=p->data_l; p->data_l=INT_MAX; p->left_child->right_child=s->left_child; free(s); p->middle_child=NULL; } void d_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { p->left_child->data_r=p->data_l; p->data_l=p->data_r; p->data_r=INT_MAX; p->left_child->right_child=s->left_child; p->middle_child=p->right_child; free(s); p->right_child=NULL; } void e_merge(two_three_ptr *t,two_three_ptr p,two_three_ptr s) { p->middle_child->data_r=p->data_r; p->data_r=INT_MAX; p->middle_child->right_child=s->left_child; free(s); p->right_child=NULL; } two_three_ptr change(two_three_ptr d,element y)//交换节点 { two_three_ptr temp; int i=0; element te; if (d->data_l==y)//左值 temp=d->left_child; else//右值 { temp=d->middle_child; i=1; } pushnode(temp,nodedel,&nodedeltop); while(temp) { if (temp->data_r != INT_MAX && temp->right_child==NULL) //(a,INT_MAX)[x,0,0,] { te=temp->data_r; temp->data_r=y; break; } else if (temp->data_r != INT_MAX && temp->right_child !=NULL) { temp=temp->right_child; pushnode(temp,nodedel,&nodedeltop); continue; } else if (temp->data_r == INT_MAX && temp->middle_child ==NULL) { te=temp->data_l; temp->data_l=y; break; } else if (temp->data_r == INT_MAX && temp->middle_child !=NULL) { temp=temp->middle_child; pushnode(temp,nodedel,&nodedeltop); continue; } } if (i==0) d->data_l=te; else d->data_r=te; popnode(nodedel,&nodedeltop);//pop掉这个temp return temp; } int main(int argc, char const *argv[]) { two_three_ptr t=NULL; insert23(&t,10); insert23(&t,40); insert23(&t,80); insert23(&t,20); insert23(&t,70); insert23(&t,30); printf("%d %d\n", search23(t,70),search23(t,80)); insert23(&t,60); insert23(&t,15); printf("%d %d\n", search23(t,10),search23(t,15)); insert23(&t,35); printf("%d %d\n", search23(t,35),search23(t,30)); two_three_ptr e=search23(t,40); two_three_ptr f=search23(t,70); printf("%d %d\n", e,f); /* --------------- 40, MAX / / -----------20,MAX 70, MAX / / / / ---10,MAX 30,MAX 60,MAX 80,MAX */ ///----------------------------- printf("\n"); delete23(&t,15); delete23(&t,30); insert23(&t,9);//(10,15)-->(9,10) insert23(&t,36);//(30,35)-->(35,36) printf("%d %d\n", search23(t,9),search23(t,10)); printf("%d %d\n", search23(t,35),search23(t,36)); //arotate delete23(&t,9); delete23(&t,10); insert23(&t,21); printf("%d %d\n", search23(t,20),search23(t,21)); //brotate delete23(&t,36); insert23(&t,22); printf("%d %d\n", search23(t,22),search23(t,35)); //crotate insert23(&t,30); insert23(&t,25); delete23(&t,35); printf("%d %d\n", search23(t,21),search23(t,25)); //amerge printf("amerge\n"); two_three_ptr t1=NULL; insert23(&t1,10); insert23(&t1,20); insert23(&t1,40); delete23(&t1,10); printf("%d %d\n", search23(t1,20),search23(t1,40)); //bmerge printf("bmerge\n"); delete23(&t,20); printf("%d %d\n", search23(t,21),search23(t,22)); //cmerge printf("cmerge\n"); two_three_ptr t2=NULL; insert23(&t2,10); insert23(&t2,20); insert23(&t2,40); delete23(&t2,40); printf("%d %d\n", search23(t2,10),search23(t2,20)); //dmerge insert23(&t,26); insert23(&t,27); delete23(&t,22); delete23(&t,26); printf("%d %d\n", search23(t,21),search23(t,25)); //cmerge和dmerge是可以合并的,c按照d的方法来即可 //emerge insert23(&t,28); insert23(&t,29); delete23(&t,30); printf("%d %d\n", search23(t,28),search23(t,29)); return 0; }
标签:2-3树
原文地址:http://blog.csdn.net/h1023417614/article/details/45971965