您的位置:首页 > 其它

AVLTree

2016-04-08 15:39 316 查看
这回好不容易做出来的数据结构是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);
}
没有很周全的测试,不过也应该差不多了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: