这回好不容易做出来的数据结构是AVLTree,做之前犹豫了好久,做的时候浪费了很多时间,做完之后还是觉得不够优化。
比如在平衡因子那一块,我不知道什么时候什么情况更新平衡因子,只好用最蠢的办法递归找。这里会浪费很多时间。
多说无益贴代码了
/*
Author: Triose
Data: 2016.4.8
Mail: triose@163.com
*/
#ifndef AVLTREE_H
#define AVLTREE_H
#include<iostream>
using namespace std;
//template<class T> T Max(T a, T b) { return a > b ? a : b; } //用于求树高, 没用了
template<class T>
class TreeElmt { //树节点定义,适当情况适当改装
public:
T data;
TreeElmt * left;
TreeElmt * right;
bool hidden;
int factor;
TreeElmt(T data_) {
this->data = data_;
this->left = NULL;
this->right = NULL;
this->hidden = false;
this->factor = 0;
}
};
template<class T>
class AVLTree {
public:
TreeElmt<T> *root;
int size;
AVLTree() {
this->root = NULL;
this->size = 0;
}
void destroy(TreeElmt<T> * _root) {
if (_root == NULL) {
return;
}
destroy(_root->left);
destroy(_root->right);
delete _root;
_root = NULL;
return;
}
~AVLTree() {
destroy(this->root);
}
int get_high(TreeElmt<T> * _root) {
if (!_root) {
return -1;
}
if (_root->factor >= 0) {
return get_high(_root->left) + 1;
}
else
return get_high(_root->right) + 1;
//return Max(get_high(_root->left), get_high(_root->right)) + 1; //其实不需要这个了。如果该节点平衡因子大于等于0,则返回左子树高度加一,否则返回右子树高度加一
}
int get_factor(TreeElmt<T> * _root) {
return get_high(_root->left) - get_high(_root->right);
}
void rotate_left(TreeElmt<T> ** _froot) {
TreeElmt<T> * _root = (_froot ? (*_froot)->left : this->root); //此处为平衡因子最先变成2的节点
TreeElmt<T> * left = _root->left;
if (left->factor == 1) {
/* LL rotate. */
_root->left = left->right;
left->right = _root;
if (_froot) {
(*_froot)->left = left;
}
else {
this->root = left;
}
_root->factor = 0;
left->factor = 0;
return;
}
else {
/* LR rotate. */
TreeElmt<T> * gchild = left->right;
left->right = gchild->left;
gchild->left = left;
_root->left = gchild->right;
gchild->right = _root;
if (_froot) {
(*_froot)->left = gchild;
}
else {
this->root = gchild;
}
switch (gchild->factor) {
case 1: _root->factor = -1; left->factor = 0; break;
case 0: _root->factor = 0; left->factor = 0; break;
case -1: _root->factor = 0; left->factor = 1; break;
}
gchild->factor = 0;
return;
}
}
void rotate_right(TreeElmt<T> ** _froot) {
TreeElmt<T> * _root = (_froot ? (*_froot)->right : this->root);
TreeElmt<T> * right = _root->right;
if (right->factor == -1) {
/* RR ratate. */
_root->right = right->left;
right->left = _root;
if (_froot) {
(*_froot)->right = right;
}
else {
this->root = right;
}
_root->factor = 0;
right->factor = 0;
return;
}
else {
/* RL rotate. */
TreeElmt<T> * gchild = right->left;
right->left = gchild->right;
gchild->right = right;
_root->right = gchild->left;
gchild->left = _root;
if (_froot) {
(*_froot)->right = gchild;
}
else {
this->root = gchild;
}
switch (gchild->factor) {
case 1: _root->factor = 0; right->factor = -1; break;
case 0: _root->factor = 0; right->factor = 0; break;
case -1: _root->factor = 1; right->factor = 0; break;
}
gchild->factor = 0;
}
}
void ins(TreeElmt<T> ** _froot, TreeElmt<T> ** _root, T data_) { //作为ADTree的插入没有问题
if (!(*_root)) {
*_root = new TreeElmt<T>(data_);
this->size++;
return;
}
if ((*_root)->data == data_) { //看节点是否被隐藏,如果不被隐藏则不做任何操作
if ((*_root)->hidden == true) {
(*_root)->hidden = false;
}
}
else if ((*_root)->data < data_) { //插入右边
ins(_root, &((*_root)->right), data_);
(*_root)->factor = get_factor(*_root);//更新平衡因子
}
else { //插入左边
ins(_root, &((*_root)->left), data_);
(*_root)->factor = get_factor(*_root);//更新平衡因子
}
/*现在判断要不要旋转,以及怎么旋转*/
if ((*_root)->factor == 2) {
rotate_left(_froot);
}
else if ((*_root)->factor == -2) {
rotate_right(_froot);
}
}
void rem(TreeElmt<T> * _root, T data_) { //惰性移除
if (_root == NULL)
return;
if (_root->data == data_) {
_root->hidden = true;
return;
}
else if (_root->data < data_) {
rem(_root->right, data_);
}
else {
rem(_root->left, data_);
}
return;
}
void Debug(TreeElmt<T> * _root) { //For Debug
if (!_root)
return;
Debug(_root->left);
if (!_root->hidden)
cout << _root->data << " " << _root->factor << endl;
Debug(_root->right);
return;
}
};
#endif // !AVLTREE_H
2016.4.12更新
上面的代码还是忽悠忽悠人吧,运行的时候太慢而且会出问题,因为树的规模一旦很大,递归来更新树高和平衡因子肯定不行,而且, C++的效率很不如C,如果在oj上用template这种东西超时的几率是很大的!
下面更新纯C模板。
#include<stdio.h>
#include<stdlib.h>
#define TYPE Node
typedef struct Node_ {
int num;
}Node;
Node* creatNode(int num_) {
Node *newnode = (Node *)malloc(sizeof(Node));
newnode->num = num_;
return newnode;
}
typedef struct TreeElmt_{
void * data;
int hight;
int factor;
int hidden;
struct TreeElmt_ * left;
struct TreeElmt_ * right;
}TreeElmt;
TreeElmt * creatElmt(void * data_) {
TreeElmt * newelement = (TreeElmt *)malloc(sizeof(TreeElmt));
newelement->data = (void *)data_;
newelement->left = NULL;
newelement->right = NULL;
newelement->factor = 0;
newelement->hight = 0;
newelement->hidden = 0;
return newelement;
}
typedef struct AVLTree_ {
TreeElmt * root;
int size;
}AVLTree;
void AVL_destroy(TreeElmt * _root) {
if (!_root)
return;
AVL_destroy(_root->left);
AVL_destroy(_root->right);
free(_root);
_root = NULL;
return;
}
void AVL_init(AVLTree * tree) {
AVL_destroy(tree->root);
tree->root = NULL;
tree->size = 0;
}
int cmp(TYPE a, TYPE b) { //a < b return -1; 直接写结构体的比较函数即可
if (a.num < b.num)
return -1;
else if (a.num == b.num)
return 0;
return 1;
}
void AVL_rem(TreeElmt * _root, void * data_) {
if (!_root)
return;
int ans = cmp(*((TYPE *)(_root->data)), *((TYPE *)(data_)));
switch (ans) {
case -1: AVL_rem(_root->right, data_); break;
case 0: _root->hidden = 1;free(data_); break;
case 1: AVL_rem(_root->left, data_); break;
}
return;
}
void reflash(TreeElmt * _root) { //更新树高和平衡因子
int lh = _root->left ? _root->left->hight : -1;
int rh = _root->right ? _root->right->hight : -1;
_root->factor = lh - rh;
_root->hight = lh > rh ? (lh + 1) : (rh + 1);
return;
}
void left_rotate(AVLTree * tree, TreeElmt ** _froot) {
TreeElmt * _root = (_froot) ? (*_froot)->left : tree->root;
TreeElmt * left = _root->left;
if (left->factor == 1) {
/* LL rotate.*/
_root->left = left->right;
left->right = _root;
if (_froot) {
(*_froot)->left = left;
}
else {
tree->root = left;
}
_root->factor = 0; //重置平衡因子并且更新树高(更新树高的顺序不能变!)
left->factor = 0;
reflash(_root);
reflash(left);
if (_froot) {
reflash(*_froot);
}
return;
}
else {
/* LR rotate.*/
TreeElmt * gchild = left->right;
left->right = gchild->left;
gchild->left = left;
_root->left = gchild->right;
gchild->right = _root;
if (_froot) {
(*_froot)->left = gchild;
}
else {
tree->root = gchild;
}
switch (gchild->factor) {
case 1: _root->factor = -1; left->factor = 0; break;
case 0: _root->factor = 0; left->factor = 0; break;
case -1: _root->factor = 0; left->factor = 1; break;
}
gchild->factor = 0; //重置平衡因子并且更新树高
reflash(left);
reflash(_root);
reflash(gchild);
if (_froot)
reflash(*_froot);
return;
}
}
void right_rotate(AVLTree * tree, TreeElmt ** _froot) {
TreeElmt * _root = (_froot ? (*_froot)->right : tree->root);
TreeElmt * right = _root->right;
if (right->factor == -1) {
/* RR ratate.*/
_root->right = right->left;
right->left = _root;
if (_froot) {
(*_froot)->right = right;
}
else {
tree->root = right;
}
_root->factor = 0; //重置平衡因子并且更新树高
right->factor = 0;
reflash(_root);
reflash(right);
if (_froot) {
reflash(*_froot);
}
return;
}
else {
/* RL rotate.*/
TreeElmt * gchild = right->left;
right->left = gchild->right;
gchild->right = right;
_root->right = gchild->left;
gchild->left = _root;
if (_froot) {
(*_froot)->right = gchild;
}
else {
tree->root = gchild;
}
switch (gchild->factor) {
case 1: _root->factor = 0; right->factor = -1; break;
case 0: _root->factor = 0; right->factor = 0; break;
case -1: _root->factor = 1; right->factor = 0; break;
}
gchild->factor = 0;
reflash(right);
reflash(_root);
reflash(gchild);
if (_froot)
reflash(*_froot);
return;
}
}
void AVL_ins(AVLTree * tree, TreeElmt ** _froot, TreeElmt ** _root, void * data_) {
if (!*_root) {
(*_root) = creatElmt(data_);
tree->size++;
return;
}
int ans = cmp(*((TYPE*)((*_root)->data)), *((TYPE*)(data_))); //比较函数
switch (ans) {
case 1: AVL_ins(tree, _root, &((*_root)->left), data_); reflash(*_root); break;
case 0: {
if ((*_root)->hidden) {
(*_root)->hidden = 0;
free(data_);
}
break;
}
case -1: AVL_ins(tree, _root, &((*_root)->right), data_); reflash(*_root); break;
}
switch ((*_root)->factor) {
case 2: left_rotate(tree, _froot);break;
case -2: right_rotate(tree, _froot);break;
default: break;
}
return;
}
void Debug(TreeElmt * _root) {
if (!_root)
return;
Debug(_root->left);
printf("%d %d\n", ((Node*)_root->data)->num, _root->factor);
Debug(_root->right);
}
AVLTree tree;
int main() {
AVL_init(&tree);
AVL_ins(&tree, NULL, &(tree.root), creatNode(27));
AVL_ins(&tree, NULL, &(tree.root), creatNode(45));
AVL_ins(&tree, NULL, &(tree.root), creatNode(34));
AVL_ins(&tree, NULL, &(tree.root), creatNode(20));
AVL_ins(&tree, NULL, &(tree.root), creatNode(11));
AVL_ins(&tree, NULL, &(tree.root), creatNode(59));
AVL_ins(&tree, NULL, &(tree.root), creatNode(10));
AVL_ins(&tree, NULL, &(tree.root), creatNode(25));
AVL_ins(&tree, NULL, &(tree.root), creatNode(29));
AVL_ins(&tree, NULL, &(tree.root), creatNode(30));
Debug(tree.root);
putchar(10);
}
没有很周全的测试,不过也应该差不多了