BST & Treap

二叉查找树递归定义:

二叉查找树是空树或不是空树
二叉查找树的左二叉查找树的值一定小于二叉查找树的值或左二叉查找树为空树
二叉查找树的右二叉查找树的值一定大于二叉查找树的值或右二叉查找树为空树

不维护父亲域的,坑爹啊。

放上代码:

#include <iostream>
#include <string>
using namespace std; #define NEW(d) new BST(d) struct BST {
BST *lc, *rc;
int data;
BST() : lc(0), rc(0) {}
BST(int d) : lc(0), rc(0), data(d) {}
}*root = NULL; typedef BST* tree; void insert(int d) {
if(root == NULL) { root = NEW(d); return;}
tree t, now = root;
//二分找到合适的位置,t是指向这个合适的位置的指针
while(now != NULL) {
t = now;
if(now-> data > d) now = now-> lc;
else now = now-> rc;
}
//插入新值到左边(或右边)
if(t-> data > d) t-> lc = NEW(d);
else t-> rc = NEW(d);
}
//没有父亲域的这个就是巨坑
void del(int d) {
tree t, q = root, rt = root;
while(rt != NULL && rt-> data != d) {
q = rt;
if(rt-> data > d) rt = rt-> lc;
else rt = rt-> rc;
}
//如果删除的是root
if(q == root) {delete root; root = NULL; return;}
//如果不存在
if(rt == NULL) return;
//如果有一边是空的,那么将另一棵子树拉上来即可,在这里,已经包含了当两边都是空树时
if(rt-> lc == NULL) {
if(q-> lc == rt) q-> lc = rt-> rc;
else q-> rc = rt-> rc;
delete rt;
return;
}
if(rt-> rc == NULL) {
if(q-> lc == rt) q-> lc = rt-> lc;
else q-> rc = rt-> lc;
delete rt;
return;
}
t = rt;
q = rt-> rc;
while(q-> lc) {
t = q;
q = q-> lc;
}
rt-> data = q-> data;
if(t != rt) t-> lc = q-> rc;
else t-> rc = q-> rc;
delete q;
} tree search(int d) {
tree ret = root;
while(ret != NULL && ret-> data != d) {
if(ret-> data > d) ret = ret-> lc;
else ret = ret-> rc;
}
return ret;
} tree max(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> rc) ret = ret-> rc;
return ret;
} tree min(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> lc) ret = ret-> lc;
return ret;
} void out(string str) {
cout << str;
} int main() {
out("1: insert\n2: del\n3: search\n4: max\n5: min\n");
int c, t;
tree a;
while(cin >> c) {
switch(c) {
case 1: cin >> t;
insert(t);
break;
case 2: cin >> t;
del(t);
break;
case 3: cin >> t;
if(search(t) == NULL) out("Not here\n");
else out("Is here!\n");
break;
case 4: a = max();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
case 5: a = min();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
default:
break;
}
}
return 0;
}

因为有些坑爹,所以还是写递归版的del

void del(tree& rt, int d) {
if(rt == NULL) return;
if(rt-> data > d) del(rt-> lc, d);
else if(rt-> data < d) del(rt-> rc, d);
else {
tree q, t;
if(rt-> lc == NULL) {
q = rt;
rt = rt-> rc;
delete q;
return;
}
if(rt-> rc == NULL) {
q = rt;
rt = rt-> lc;
delete q;
return;
}
q = rt-> rc, t = rt;
//找后继
while(q-> lc != NULL) {
t = q;
q = q-> lc;
}
rt-> data = q-> data;
//当后继就是右子女,那么要将后继的右子女接到节点右边
if(rt == t) t-> rc = q-> rc;
//否则就要给后继的父亲的左子女赋值为后继的右子女
else t-> lc = q-> rc;
delete q;
}
}

写个简洁的把,,,维护个父亲域。。旋转也好写了= =。

#include <iostream>
#include <string>
using namespace std; #define NEW(d) new BST(d) struct BST {
BST *lc, *rc, *pa;
int data;
BST() : lc(0), rc(0), pa(0) {}
BST(int d) : lc(0), rc(0), pa(0), data(d) {}
//BST operator= (BST& a) { lc = a.lc; rc = a.rc; pa = a.pa; data = a.data; return *this; }
}*root = NULL; typedef BST* tree; void insert(int d) {
if(root == NULL) { root = NEW(d); return;}
tree t, now = root;
//二分找到合适的位置,t是指向这个合适的位置的指针
while(now != NULL) {
t = now;
if(now-> data > d) now = now-> lc;
else now = now-> rc;
}
//插入新值到左边(或右边)
if(t-> data > d) t-> lc = NEW(d), t-> lc-> pa = t;
else t-> rc = NEW(d), t-> rc-> pa = t;
} tree search(int d) {
tree ret = root;
while(ret != NULL && ret-> data != d) {
if(ret-> data > d) ret = ret-> lc;
else ret = ret-> rc;
}
return ret;
} void del(int d) {
tree rt = search(d), t, q;
if(rt == root) { delete root; root = NULL; return; }
if(rt == NULL) return;
if(rt-> lc == NULL) {
if(rt-> pa-> lc == rt) rt-> pa-> lc = rt-> rc;
else rt-> pa-> rc = rt-> rc;
delete rt;
return;
}
if(rt-> rc == NULL) {
if(rt-> pa-> lc == rt) rt-> pa-> lc = rt-> lc;
else rt-> pa-> rc = rt-> lc;
delete rt;
return;
}
q = rt-> rc, t = rt;
while(q-> lc) {
t = q;
q = q-> lc;
}
rt-> data = q-> data;
if(t != rt) t-> rc = q-> rc;
else t-> lc = q-> rc;
delete q;
} tree max(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> rc) ret = ret-> rc;
return ret;
} tree min(){
if(root == NULL) return NULL;
tree ret = root;
while(ret-> lc) ret = ret-> lc;
return ret;
} void out(string str) {
cout << str;
} int main() {
out("1: insert\n2: del\n3: search\n4: max\n5: min\n");
int c, t;
tree a;
while(cin >> c) {
switch(c) {
case 1: cin >> t;
insert(t);
break;
case 2: cin >> t;
del(t);
break;
case 3: cin >> t;
if(search(t) == NULL) out("Not here\n");
else out("Is here!\n");
break;
case 4: a = max();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
case 5: a = min();
if(a != NULL) cout << a-> data << endl;
else out("Warn!\n");
break;
default:
break;
}
}
return 0;
}

  

 

上一篇:ue4 FPaths各目录


下一篇:JavaScript 中 onload 事件绑定多个方法