应该算比较精简了,不过 指针 和 指向指针的指针 实在头疼!
#include "stdio.h"
#include "stdlib.h"
typedef struct _Node{
int val;
int rev;
int child;
struct _Node* pre;
struct _Node* ch[2]; //0,左孩子; 1,右孩子;
}Node, *pNode;
int n, m;
pNode root;
/*更新节点的孩子数*/
void update(pNode r){
int lf, rt;
lf = r->ch[0]?(r->ch[0]->child+1):0;
rt = r->ch[1]?(r->ch[1]->child+1):0;
r->child = lf+rt;
}
void insert(pNode* r, int data){
pNode w = *r;
if(!w){
w = (pNode)malloc(sizeof(Node));
w->val = data;
w->child = 0;
w->rev = 0;
w->pre = 0;
w->ch[0] = w->ch[1] = 0;
*r = w;
return;
}
if(data > w->val){
insert(&(w->ch[1]), data);
if(w->ch[1]->child==0) w->ch[1]->pre = w;
}else{
insert(&(w->ch[0]), data);
if(w->ch[0]->child==0) w->ch[0]->pre = w;
}
update(w);
}
/*旋转,0为往左旋转,1为往右旋转。旋转要注意各种指针的更新,要仔细啊!*/
void rotate(pNode* r, int op){ //0,lf; 1,rt;
pNode t, w = *r;
t = w->ch[!op]; //获得左/右孩子
w->ch[!op] = t->ch[op];
if(t->ch[op]) t->ch[op]->pre = w;
t->ch[op] = w;
t->pre = w->pre;
if(w->pre){ //更新w父节点的孩子指针
if(w == w->pre->ch[0])
w->pre->ch[0] = t;
else
w->pre->ch[1] = t;
}else
root = t; //这句非常重要!!!如果t旋转到了最顶点,即w->pre为0,那么要更新root指向!
w->pre = t;
update(w);
update(t);
*r = t; //将新的节点赋值到*r中
}
/*如果r被标记,则旋转r的“直接”子树,并将标记下传到“直接”孩子*/
void push(pNode r){
pNode t;
if(r && r->rev){
t = r->ch[0];
r->ch[0] = r->ch[1];
r->ch[1] = t;
r->rev = 0;
if(r->ch[0])
r->ch[0]->rev ^= 1;
if(r->ch[1])
r->ch[1]->rev ^= 1;
}
}
/*寻找中序遍历的第k个节点*/
pNode find(int k, pNode r){
int t;
if(!r) return 0;
push(r);
t = r->ch[0]?(r->ch[0]->child+1):0;
if(k==t+1)
return r;
if(k>t+1)
return find(k-t-1, r->ch[1]);
else
return find(k, r->ch[0]);
}
/*伸展运动,将a旋转到b的下面。当b为0时,即,将a旋转为root*/
void splay(pNode a, pNode b){
pNode k;
k = a->pre;
if(!k || k==b)
return;
if(a==k->ch[0])
rotate(&k, 1);
else
rotate(&k, 0);
splay(k, b);
}
void show(pNode r){
if(!r) return;
show(r->ch[0]);
printf("%d ", r->val);
show(r->ch[1]);
}
/*删除树,养成好习惯。不过要稍微多耗一点时间*/
void del(pNode r){
if(!r) return;
del(r->ch[0]);
del(r->ch[1]);
free(r);
}
void main(){
int i;
for(i=0; i<10; i++)
insert(&root, i);
show(root); printf("\n");
del(root);
}