您的位置:首页 > 编程语言 > C语言/C++

红黑树的C++实现(1)

2015-11-27 15:11 567 查看
三年前磕磕盼盼用C语言写过红黑树,这段时间用C++重写了红黑树,修复了之前代码中的一些错误。记得以前的博客里面就写过使用C++写红黑树更容易些,因为可以重用二叉搜索树的C++代码。照例,首先实现二叉搜索树,然后再实现红黑树。

首先,定义二叉树结点的类,btnode.h:

#ifndef __BTNODE_H__
#define __BTNODE_H__
#include <stdexcept>
#include <typeinfo>

using std::logic_error;

template <typename T>
struct CBinaryTreeNode
{
enum eColor {
RED,
BLACK
};

CBinaryTreeNode(const T& val, CBinaryTreeNode<T>* parent = NULL, CBinaryTreeNode<T>* left = NULL, CBinaryTreeNode<T>* right = NULL, eColor color = RED);
virtual ~CBinaryTreeNode();

virtual bool operator==(const CBinaryTreeNode<T>& node);
virtual bool operator<(const CBinaryTreeNode<T>& node);
virtual bool operator>(const CBinaryTreeNode<T>& node);

T key;
CBinaryTreeNode<T> *parent;
CBinaryTreeNode<T> *left;
CBinaryTreeNode<T> *right;

eColor color;
};

template <typename T>
CBinaryTreeNode<T>::CBinaryTreeNode(const T& val, CBinaryTreeNode<T>* parent, CBinaryTreeNode<T>* left, CBinaryTreeNode<T>* right, eColor color)
{
key = val;
this->parent = parent;
this->left = left;
this->right = right;
this->color = color;
}

template<typename T>
CBinaryTreeNode<T>::~CBinaryTreeNode()
{

}

template <typename T>
bool CBinaryTreeNode<T>::operator==(const CBinaryTreeNode<T>& node)
{
if (typeid(*this) != typeid(node))
throw logic_error("diffrent type objects.");

return this->key == node.key;
}

template <typename T>
bool CBinaryTreeNode<T>::operator<(const CBinaryTreeNode<T>& node)
{
if (typeid(*this) != typeid(node))
throw logic_error("diffrent type objects.");

return this->key < node.key;
}

template <typename T>
bool CBinaryTreeNode<T>::operator>(const CBinaryTreeNode<T>& node)
{
if (typeid(*this) != typeid(node))
throw logic_error("diffrent type objects.");

return this->key > node.key;
}

#endif
然后,定义二叉搜索树的类,bst.h:

#ifndef __BST_H__
#define __BST_H__
#include <iostream>
#include "btnode.h"

using std::cout;
using std::endl;

template <typename T>
class CBinarySortTree
{
public:
CBinarySortTree();
~CBinarySortTree() {}

virtual CBinaryTreeNode<T>* Insert(const T& key);
virtual void Delete(CBinaryTreeNode<T>** del);
virtual CBinaryTreeNode<T>* Search(const T& key) const;
virtual CBinaryTreeNode<T>* Search(CBinaryTreeNode<T>* node, const T& key) const;
virtual void InorderWalk() const;

protected:
CBinaryTreeNode<T>* SearchMinOnRightChild(CBinaryTreeNode<T>* val);
CBinaryTreeNode<T>* Transplant(CBinaryTreeNode<T>* u, CBinaryTreeNode<T>* v);
void InorderWalk(const CBinaryTreeNode<T>* root) const;

CBinaryTreeNode<T>* root;
static CBinaryTreeNode<T> sentinel;
};

template <typename T>
CBinaryTreeNode<T> CBinarySortTree<T>::sentinel(0, &sentinel, &sentinel, &sentinel, CBinaryTreeNode<T>::BLACK);

template <typename T>
CBinarySortTree<T>::CBinarySortTree()
{
root = &sentinel;
root->parent = &sentinel;
root->left = &sentinel;
root->right = &sentinel;
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::Insert(const T& key)
{
CBinaryTreeNode<T> *p = NULL;

if (root == &sentinel) {
p = new CBinaryTreeNode<T>(key, &sentinel, &sentinel, &sentinel);
root = p;
} else {
p = root;
CBinaryTreeNode<T> *parent = &sentinel;
CBinaryTreeNode<T> *node = new CBinaryTreeNode<T>(key, &sentinel, &sentinel, &sentinel);

while (p != &sentinel) {
parent = p;

if (*p < *node)
p = p->right;
else
p = p->left;
}

node->parent = parent;
if (*parent < *node)
parent->right = node;
else
parent->left = node;

p = node;
}

return p;
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::SearchMinOnRightChild(CBinaryTreeNode<T>* node)
{
while (node->left != &sentinel)
node = node->left;

return node;
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::Transplant(CBinaryTreeNode<T>* u, CBinaryTreeNode<T>* v)
{
CBinaryTreeNode<T>* d = NULL;

if (u->parent == &sentinel) {
d = root;
root = v;
} else {
d = u;
if (u == u->parent->left)
u->parent->left = v;
else
u->parent->right = v;
}

v->parent = u->parent;

return d;
}

template <typename T>
void CBinarySortTree<T>::Delete(CBinaryTreeNode<T>** del)
{
CBinaryTreeNode<T>* node = *del;
CBinaryTreeNode<T>* n = &sentinel;

if (node->left == &sentinel && node->right == &sentinel) {
CBinaryTreeNode<T>* parent = node->parent;

if (parent != &sentinel) {
if (parent->left == node)
parent->left = &sentinel;
else
parent->right = &sentinel;
} else {
*del = &sentinel;
root = &sentinel;
}

delete node;
} else if (node->left == &sentinel && node->right != &sentinel) {
n = Transplant(node, node->right);
delete n;
} else if (node->left != &sentinel && node->right == &sentinel) {
n = Transplant(node, node->left);
delete n;
} else {
n = SearchMinOnRightChild(node->right);

if (n->parent != node) {
Transplant(n, n->right);
n->right = node->right;
n->right->parent = n;
}

CBinaryTreeNode<T>* temp = Transplant(node, n);
n->left = node->left;
n->left->parent = n;

delete temp;
}
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::Search(CBinaryTreeNode<T>* node, const T& key) const
{
if (node != &sentinel) {
CBinaryTreeNode<T> n(key);

if (*node < n)
return Search(node->right, key);
else if (*node > n)
return Search(node->left, key);
else
return node;
}

return NULL;
}

template <typename T>
CBinaryTreeNode<T>* CBinarySortTree<T>::Search(const T& key) const
{
return Search(root, key);
}

template <typename T>
void CBinarySortTree<T>::InorderWalk() const
{
InorderWalk(root);
}

template <typename T>
void CBinarySortTree<T>::InorderWalk(const CBinaryTreeNode<T>* node) const
{
const CBinaryTreeNode<T>* p = node;

if (p != &sentinel) {
InorderWalk(p->left);
cout << p->key << ' ';
InorderWalk(p->right);
}
}
#endif
测试二叉搜索树的代码,bst_test.cpp:

#include "bst.h"

int main(int argc, const char **argv)
{
int key[] = { 12, 1, 9, 2, 0, 11, 7, 19, 4, 15, 18, 5, 14, 13, 10, 16, 6, 3, 8, 17 };

CBinarySortTree<int> bst;

cout << "original key: ";
for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i)
cout << key[i] << ' ';

cout << endl;
for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i)
bst.Insert(key[i]);

cout << "after insertion: ";
bst.InorderWalk();
cout << endl;

for (size_t i = 0; i < sizeof(key) / sizeof(int); ++i) {
CBinaryTreeNode<int>* del = bst.Search(key[i]);
if (del) {
cout << "after " << i + 1 << " time(s) deletion: ";
bst.Delete(&del);
bst.InorderWalk();
cout << endl;
}
}

return 0;
}
红黑树重用了大多数二叉树的接口,将在下一篇介绍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: