这并不是直接回答问题,但你是否阅读过Sedgewick关于左偏红黑树的论文?其中的代码非常清晰,有美丽的图表解释了如何运作,而且我想,将所有东西重新实现到C++中应该很简单。
![Sedgewick's Insert Function](https://istack.dev59.com/jS4T9.webp)
![Sedgewick's rotate function](https://istack.dev59.com/vxMkD.webp)
编辑
我为了好玩尝试实现Sedgewick的代码。结果发现论文中漏掉了一些方法/子程序,包含它们将会非常有帮助。无论如何,我的C++11实现和一些测试如下。
由于Java具有自动内存管理,Sedgewick在他的代码中没有明确指出应该释放哪些内存。为了避免在快速项目中尝试弄清楚这一点并可能留下内存泄漏,我选择使用std::shared_ptr
,它提供了类似于无需担心的行为。
#include <iostream>
#include <vector>
#include <cstdlib>
#include <memory>
template<class keyt, class valuet>
class LLRB {
private:
static const bool COLOR_RED = true;
static const bool COLOR_BLACK = false;
class Node {
public:
keyt key;
valuet val;
std::shared_ptr<Node> right;
std::shared_ptr<Node> left;
bool color;
Node(keyt key, valuet val){
this->key = key;
this->val = val;
this->color = COLOR_RED;
this->right = nullptr;
this->left = nullptr;
}
};
typedef std::shared_ptr<Node> nptr;
nptr root;
nptr rotateLeft(nptr h){
nptr x = h->right;
h->right = x->left;
x->left = h;
x->color = h->color;
h->color = COLOR_RED;
return x;
}
nptr rotateRight(nptr h){
nptr x = h->left;
h->left = x->right;
x->right = h;
x->color = h->color;
h->color = COLOR_RED;
return x;
}
nptr moveRedLeft(nptr h){
flipColors(h);
if(isRed(h->right->left)){
h->right = rotateRight(h->right);
h = rotateLeft(h);
flipColors(h);
}
return h;
}
nptr moveRedRight(nptr h){
flipColors(h);
if(isRed(h->left->left)){
h = rotateRight(h);
flipColors(h);
}
return h;
}
void flipColors(nptr h){
h->color = !h->color;
h->left->color = !h->left->color;
h->right->color = !h->right->color;
}
bool isRed(const nptr h) const {
if(h==nullptr) return false;
return h->color == COLOR_RED;
}
nptr fixUp(nptr h){
if(isRed(h->right) && !isRed(h->left)) h = rotateLeft (h);
if(isRed(h->left) && isRed(h->left->left)) h = rotateRight(h);
if(isRed(h->left) && isRed(h->right)) flipColors (h);
return h;
}
nptr insert(nptr h, keyt key, valuet val){
if(h==nullptr)
return std::make_shared<Node>(key,val);
if (key == h->key) h->val = val;
else if(key < h->key) h->left = insert(h->left, key,val);
else h->right = insert(h->right,key,val);
h = fixUp(h);
return h;
}
nptr deleteMin(nptr h){
if(h->left==nullptr) return nullptr;
if(!isRed(h->left) && !isRed(h->left->left))
h = moveRedLeft(h);
h->left = deleteMin(h->left);
return fixUp(h);
}
nptr minNode(nptr h){
return (h->left == nullptr) ? h : minNode(h->left);
}
nptr remove(nptr h, keyt key){
if(key<h->key){
if(!isRed(h->left) && !isRed(h->left->left))
h = moveRedLeft(h);
h->left = remove(h->left, key);
} else {
if(isRed(h->left))
h = rotateRight(h);
if(key==h->key && h->right==nullptr)
return nullptr;
if(!isRed(h->right) && !isRed(h->right->left))
h = moveRedRight(h);
if(key==h->key){
std::shared_ptr<Node> mn = minNode(h->right);
h->val = mn->val;
h->key = mn->key;
h->right = deleteMin(h->right);
} else {
h->right = remove(h->right, key);
}
}
return fixUp(h);
}
void traverse(const nptr h) const {
if(h==nullptr)
return;
traverse(h->left);
std::cout<< h->key << "=" << h->val <<std::endl;
traverse(h->right);
}
public:
LLRB(){
root = nullptr;
}
void traverse() const {
traverse(root);
}
valuet search(keyt key){
nptr x = root;
while(x!=nullptr){
if (key == x->key) return x->val;
else if (key < x->key) x=x->left;
else x=x->right;
}
return keyt();
}
void insert(keyt key, valuet val){
root = insert(root,key,val);
root->color = COLOR_BLACK;
}
void remove(keyt key){
root = remove(root,key);
root->color = COLOR_BLACK;
}
};
int main(){
for(int test=0;test<500;test++){
LLRB<int,int> llrb;
std::vector<int> keys;
std::vector<int> vals;
for(int i=0;i<1000;i++){
int newkey = rand();
while(llrb.search(newkey)!=int())
newkey = rand();
keys.push_back(newkey);
vals.push_back(rand()+1);
llrb.insert(keys.back(),vals.back());
}
for(int i=0;i<1000;i++){
if(llrb.search(keys[i])!=vals[i]){
return -1;
}
}
for(int i=0;i<500;i++)
llrb.remove(keys[i]);
for(int i=500;i<1000;i++){
if(llrb.search(keys[i])!=vals[i]){
return -1;
}
}
}
std::cout<<"Good"<<std::endl;
}