欢迎探讨,若有错误敬请指正 html
如需转载,请注明出处http://www.cnblogs.com/nullzx/ java
AVL树是一种改进版的搜索二叉树。对于通常的搜索二叉树而言,若是数据刚好是按照从小到大的顺序或者从大到小的顺序插入的,那么搜索二叉树就对退化成链表,这个时候查找,插入和删除的时间都会上升到O(n),而这对于海量数据而言,是咱们没法忍受的。即便是一颗由彻底随机的数据构形成的搜索二叉树,从统计角度去分析,在进行若甘次的插入和删除操做,这个搜索二叉树的高度也不能使人满意。这个时候你们就但愿能有一种二叉树解决上述问题。这个时候就出现平衡搜索二叉树,它的基本原理就是在插入和删除的时候,根据状况进行调整,以下降二叉树的高度。平衡搜索二叉树典型表明就是AVL树和红黑树。 ide
AVL树:任何一个节点的左子支高度与右子支高度之差的绝对值不超过1。须要咱们注意的是,AVL树定义不是说从根节点到叶子节点的最短距离比最长短距离大1。 函数
上图就是一颗AVL树,从根节点到叶子节点的最短距离是5,最长距离是9。 测试
由于每种书中对旋转的定义不一致,因此咱们有必要在这里特此说明一下 this
以某一个节点为轴,它的左子枝顺时针旋转,做为新子树的根,咱们称之为顺时针旋转(clockwise)或者右旋转。 3d
同理,以某一个节点为轴,它的右子枝逆针旋转,做为新子树的根,咱们称之为逆时针旋转(anticlockwise)或者左旋转。 指针
AVL树的插入操做首先会按照普通搜索二叉树的插入操做进行,当插入一个数据后,咱们会沿着插入数据时所通过的的节点回溯,回溯的过程当中会判回溯路径中的每一个节点的左子支高度与右子支高度之差的绝对值是否超过1,若是超过1咱们就进行调整,调整的目的是使得该节点知足AVL树的定义。调整的状况能够分为如下四旋转操做,旋转操做能够下降树的高度,同时不改变搜索二叉树的性质(即任何一个节点左子支中的所有节点小于该节点,右子支的所有节点大于该节点)。 调试
节点X左子支比右子支高度大2,且插入的节点位于X的左孩子节点XL的左子支上 htm
节点X右子支比左子支高度大2,且插入的节点位于节点X右孩子节点XR的右子支上
节点X左子支比右子支高度大2,且插入的节点位于节点X左孩子节点XL的右子支上
节点X左子支比右子支高度大2,且插入的节点位于节点X左孩子节点XL的右子支上
AVL树的删除操做和插入操做同样,首先会按照普通搜索二叉树的删除操做进行,当删除一个数据后,和插入操做同样,咱们一般采起的策略是沿着删除数据时所通过的的节点回溯,回溯的过程当中会判断该节点的左子支高度与右子支高度之差的绝对值是否超过1(或者说大2),若是超过1,咱们就进行调整,调整的目的是使得该节点知足AVL树的定义。调整的状况能够分为四种,和插入过程彻底同样,这里不在赘述。
AVLtree.h文件中的内容
#ifndef __AVLTREE_H__ #define __AVLTREE_H__ typedef struct Node{ int height; //该节点做为子树时的高度 int data; //表示每一个节点存贮的数据 Node* left; Node* right; }Node, *AVLtree; //AVLtree 表示Node* //AVLtree* 就表示Node** int Insert(AVLtree* T, int D); int Delete(AVLtree* T, int D); int Find(AVLtree T, int x); int Destroy(AVLtree* T); //下面两个遍历函数主要用于测试 void InOredrTraverse(AVLtree T); void PreOredrTraverse(AVLtree T); #endif
AVLtree.cpp文件中的内容
#include"AVLtree.h" #include<stdlib.h> #include<stdio.h> #define MAX(x1,x2) ((x1) > (x2) ? (x1) : (x2)) //一下函数用于辅助实现插入删除操做,做用域于仅限于AVLtree.cpp static void PostOrderTraverse(AVLtree T); static int GetHeight(AVLtree T); static void LeftRotate(AVLtree* T); static void RightRotate(AVLtree* T); static int FindMin(AVLtree T); //返回值用于表示插入是否成功,-1表示失败(说明树中已包含该数据),0表示成功 int Insert(AVLtree* T,int D){ //参数检查 if(T == NULL){ return -1; } //找到插入的位置 if(*T == NULL){ *T = (Node*)malloc(sizeof(Node)); (*T)->data = D; (*T)->height = 1; (*T)->left = NULL; (*T)->right = NULL; return 0; }else{ //树中已存在该数据 if(D == (*T)->data){ return -1; }else if(D > (*T)->data){//在右子树中插入 if(Insert(&(*T)->right,D) == -1){ return -1; } //插入后,当回溯到该节点进行检查,若是不知足平衡条件,则调整 //由于是在右子支中插入,若是高度只差等于2,只多是右子支比左子支高 if(GetHeight((*T)->right) - GetHeight((*T)->left) == 2){ if(D > (*T)->right->data){ LeftRotate(T);//对应状况2,左旋 }else{//对应状况4,先右旋再左旋 RightRotate(&(*T)->right); LeftRotate(T); } } }else if(D < (*T)->data){//在左子树中插入 if(Insert(&(*T)->left,D)){ return -1; } if(GetHeight((*T)->left) - GetHeight((*T)->right) == 2){ if(D < (*T)->left->data){ RightRotate(T);//对应状况1,左旋 }else{//对应状况3,先右旋再左旋 LeftRotate(&(*T)->left); RightRotate(T); } } } } //更新当前节点的高度 (*T)->height = MAX(GetHeight((*T)->left),GetHeight((*T)->right))+1; return 0; } //返回-1表示,树中没有该数据,删除失败, int Delete(AVLtree* T,int D){ static Node* tmp; if(T == NULL){ return -1; } if(*T == NULL){//树为空,或者树中没有该数据 return -1; }else{ //找到要删除的节点 if(D == (*T)->data){ //删除的节点左右子支都不为空,必定存在前驱节点 if((*T)->left != NULL && (*T)->right != NULL){ D = FindMin((*T)->right);//找后继替换 (*T)->data = D; Delete(&(*T)->right,D);//而后删除后继节点,必定成功 //在右子支中删除,删除后有可能左子支比右子支高度大2 if(GetHeight((*T)->left)-GetHeight((*T)->right) == 2){ //判断哪个左子支的的两个子支哪一个比较高 if(GetHeight((*T)->left->left) >= GetHeight((*T)->left->right)){ RightRotate(T); }else{ LeftRotate(&(*T)->left); RightRotate(T); } } }else if((*T)->left == NULL){//左子支为空 tmp = (*T); (*T) = tmp->right; free(tmp); return 0; }else if((*T)->right == NULL){//右子支为空 tmp = (*T); (*T) = tmp->left; free(tmp); return 0; } }else if(D > (*T)->data){//在右子支中寻找待删除的节点 if(Delete(&(*T)->right,D) == -1){ return -1;//删除失败,不须要调整,直接返回 } if(GetHeight((*T)->left)-GetHeight((*T)->right) == 2){ if(GetHeight((*T)->left->left) >= GetHeight((*T)->left->right)){ RightRotate(T); }else{ LeftRotate(&(*T)->left); RightRotate(T); } } }else if(D < (*T)->data){//在左子支中寻找待删除的节点 if(Delete(&(*T)->left,D) == -1){ return -1; } if(GetHeight((*T)->right) - GetHeight((*T)->left) == 2){ if(GetHeight((*T)->right->right) >= GetHeight((*T)->right->left)){ LeftRotate(T); }else{ RightRotate(&(*T)->right); LeftRotate(T); } } } } //更新当前节点的高度 (*T)->height = MAX(GetHeight((*T)->left),GetHeight((*T)->right))+1; return 0; } int Find(AVLtree T,int x){ while(T != NULL){ if(T->data == x){ return 0; }else if(x > T->data){ T = T->right; }else{ T = T->left; } } return -1; } int Destroy(AVLtree* T){ if(T == NULL){ return -1; } PostOrderTraverse(*T); *T = NULL; return 0; } void InOredrTraverse(AVLtree T){ if(T != NULL){ InOredrTraverse(T->left); printf("%3d ",T->data); InOredrTraverse(T->right);; } } void PreOredrTraverse(AVLtree T){ if(T != NULL){ printf("%3d:%2d(%3d,%3d)\n",T->data,T->height, T->left == NULL?-1:T->left->data, T->right == NULL?-1:T->right->data ); PreOredrTraverse(T->left); PreOredrTraverse(T->right); } } static void PostOrderTraverse(AVLtree T){ if(T != NULL){ PostOrderTraverse(T->left); PostOrderTraverse(T->right); free(T); } } //空数的高度为0 static int GetHeight(AVLtree T){ if(T == NULL){ return 0; }else{ return T->height; } } static void LeftRotate(AVLtree* T){ Node *P,*R; P = *T; R = P->right; P->right = R->left; R->left = P; *T = R; //旋转之后要更新节点的高度 P->height = MAX(GetHeight(P->left),GetHeight(P->right))+1; R->height = MAX(GetHeight(R->left),GetHeight(R->right))+1; } static void RightRotate(AVLtree* T){ Node *P,*L; P = *T; L = P->left; P->left = L->right; L->right = P; *T = L; //旋转之后要更新节点的高度 P->height = MAX(GetHeight(P->left),GetHeight(P->right))+1; L->height = MAX(GetHeight(L->left),GetHeight(L->right))+1; } static int FindMin(AVLtree T){ if(T == NULL){ return -1; } while(T->left != NULL){ T = T->left; } return T->data; }
package datastruct; import java.util.Comparator; public class AVLtree <E>{ private static class Node<E>{ int h; E element; Node<E> left; Node<E> right; //因为java中不像C语言那样有二级指针的概念,因此添加一个父类的引用,方便程序编写 Node<E> parent; public Node(E element, int h, Node<E> left, Node<E> right, Node<E> parent){ this.element = element; this.h = h; this.left = left; this.right = right; this.parent = parent; } } private Node<E> root;//指向伪根节点的引用 private int size = 0;//节点个数 Comparator<? super E> cmp;//节点大小的比较器 //若是调用了不带参数的构造函数,则使用该内部类做为比较器, //但此时泛型E须要继承Comparable接口,不然运行时会抛出异常 private static class Cmp<T> implements Comparator<T>{ @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public int compare(T e1, T e2) { return ((Comparable)e1).compareTo(e2); } } //带比较器的构造函数 public AVLtree(Comparator<? super E> cmp){ if(cmp == null){ throw new IllegalArgumentException(); } this.cmp = cmp; //建立一个伪根节点,该节点的右子支才是真正的AVL树的根 //使用伪根节点节点的目的是,对插入和删除操做递归的形式可以统一 root = new Node<E>(null, -1, null, null, null); } //不带比较器的构造函数 public AVLtree(){ this.cmp = new Cmp<E>(); root = new Node<E>(null, -1, null, null, null); } //若是树中节点有变更,从底向上逐级调用该函数,能够更新节点的高度 private int getHight(Node<E> x){ if(x == null){ return 0; }else{ return x.h; } } //求某个节点做为根时,该子树的最小值 private E treeMin(Node<E> x){ while(x.left != null){ x = x.left; } return x.element; } public int size(){ return size; } //先根遍历,调试时使用 public void preorderTraverse(){ if(root != null){ preorderTraverse0(root.right); } } private void preorderTraverse0(Node<E> x){ if(x != null){ System.out.print(x.element+" "); if(x.left != null){ System.out.print(x.left.element+" "); }else{ System.out.print("null "); } if(x.right != null){ System.out.print(x.right.element+" "); }else{ System.out.print("null "); } System.out.println(); preorderTraverse0(x.left); preorderTraverse0(x.right); } } //逆时针旋转(左旋),参数表示轴节点 private void antiClockwiseRotate(Node<E> X){ Node<E> P = X.parent; Node<E> XR = X.right; if(P.left == X){ P.left = XR; }else{ P.right = XR; } XR.parent = P; X.right = XR.left; if(XR.left != null){ XR.left.parent = X; } XR.left = X; X.parent = XR; //旋转后要更新这两个节点的高度 X.h = Math.max(getHight(X.left), getHight(X.right)) + 1; XR.h = Math.max(getHight(XR.left), getHight(XR.right)) + 1; } //顺时针旋转(右旋),参数表示轴节点 private void clockwistRotate(Node<E> X){ Node<E> P = X.parent; Node<E> XL = X.left; if(P.left == X){ P.left = XL; }else{ P.right = XL; } XL.parent = P; X.left = XL.right; if(XL.right != null){ XL.right.parent = X; } XL.right = X; X.parent = XL; //旋转后要更新这两个节点的高度 X.h = Math.max(getHight(X.left), getHight(X.right)) + 1; XL.h = Math.max(getHight(XL.left), getHight(XL.right)) + 1; } // public void insert(E e){ insert0(root.right, e); } private void insert0(Node<E> x, E e){ if(x == null){ root.right = new Node<E>(e, 1, null, null, root);//根节点 size++; return; } if(cmp.compare(e, x.element) > 0){ if(x.right != null){ insert0(x.right, e); int lh = getHight(x.left); int rh = getHight(x.right); if(rh - lh == 2){ if(cmp.compare(e, x.right.element) > 0){ antiClockwiseRotate(x); }else{ clockwistRotate(x.right); antiClockwiseRotate(x); } } }else{ size++; x.right = new Node<E>(e, 1, null, null, x); } }else if(cmp.compare(e, x.element) < 0){ if(x.left != null){ insert0(x.left, e); int lh = getHight(x.left); int rh = getHight(x.right); if(lh - rh == 2){ if(cmp.compare(e, x.left.element) < 0){ clockwistRotate(x); }else{ antiClockwiseRotate(x.left); clockwistRotate(x); } } }else{ size++; x.left = new Node<E>(e, 1, null, null, x); } }else{ //元素已存在,咱们用新的元素更新旧, //compare返回值等于0,并不表示两个对象彻底相等 x.element = e; } x.h = Math.max(getHight(x.left), getHight(x.right)) + 1; } public boolean delete(E e){ return delete0(root.right, e); } //返回值表示是否删除成功 private boolean delete0(Node<E> x, E e){ if(x == null){//没有找到待删除的元素 return false; } if(cmp.compare(e, x.element) > 0){ boolean reval = delete0(x.right, e); if(reval == false){ return false; } int lh = getHight(x.left); int rh = getHight(x.right); if(lh - rh == 2){ if(getHight(x.left.left) > getHight(x.left.right)){ clockwistRotate(x); }else{ antiClockwiseRotate(x.left); clockwistRotate(x); } } }else if(cmp.compare(e, x.element) < 0){ boolean reval = delete0(x.left, e); if(reval == false){ return false; } int lh = getHight(x.left); int rh = getHight(x.right); if(rh - lh == 2){ if(getHight(x.right.right) > getHight(x.right.left)){ antiClockwiseRotate(x); }else{ clockwistRotate(x.right); antiClockwiseRotate(x); } } }else{//找到待删除的元素 Node<E> P = x.parent; if(x.left == null){//左子支为空,可直接删除,在这一层必定不须要旋转 size--; if(P.left == x){ P.left = x.right; if(P.left != null){ P.left.parent = P; } }else{ P.right = x.right; if(P.right != null){ P.right.parent = P; } } }else if(x.right == null){//右子支为空,可直接删除,在这一层必定不须要旋转 size--; if(P.left == x){ P.left = x.left; if(P.left != null){ P.left.parent = P; } }else{ P.right = x.left; if(P.right != null){ P.right.parent = P; } } }else{//找到待删除的节点,用后继节点代替,而后删除后继节点 E nextVal = treeMin(x.right); x.element = nextVal; delete0(x.right, nextVal); int lh = getHight(x.left); int rh = getHight(x.right); if(lh - rh == 2){ if(getHight(x.left.left) > getHight(x.left.right)){ clockwistRotate(x); }else{ antiClockwiseRotate(x.left); clockwistRotate(x); } } } } x.h = Math.max(getHight(x.left), getHight(x.right)) + 1; return true; } public static void main(String[] args){ AVLtree<Integer> avl = new AVLtree<Integer>(); /*可自行添加插入,删除操做进行测试*/ avl.insert(3); avl.insert(5); avl.insert(6); avl.insert(7); avl.insert(8); avl.insert(9); avl.preorderTraverse(); System.out.println(); System.out.println(avl.size()); avl.delete(7); avl.delete(8); avl.preorderTraverse(); System.out.println(); System.out.println(avl.size()); } }