这回好不容易做出来的数据结构是AVLTree,做之前犹豫了好久,做的时候浪费了很多时间,做完之后还是觉得不够优化。
比如在平衡因子那一块,我不知道什么时候什么情况更新平衡因子,只好用最蠢的办法递归找。这里会浪费很多时间。
多说无益贴代码了
/* Author: Triose Data: 2016.4.8 Mail: [email protected] */ #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); }没有很周全的测试,不过也应该差不多了