平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树

平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树

(a)和(b)都是排序二叉树,但是查找(b)的93节点就需要查找6次,查找(a)的93节点就需要查找3次,所以(b)的效率不高。

平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树。它或者是一颗空树,或者是具有下列性质的二叉树:它的左子树和右子树的深度只差的绝对值不超过1。若将二叉树上节点的平衡因子BF(Balance Factor)定义为该节点的左子树的深度减去它右子树的深度,则平衡二叉树上所有节点的平衡因子只可能是-1,0,1。只要二叉树上有一个节点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。

上图(a)是平衡二叉树,(b)不是平衡二叉树,因为有的节点的平衡因子大于1了。

插入节点的大致思路:

  • 首先找到插入节点的位置,插入节点
  • 插入节点后,调整相关节点的平衡因子
  • 调整平衡因子后,如果发现树不平衡了,就要进行节点的调整(单左旋转,或单右旋转,或双旋转(先左后又,或者先右后左)。

avl_tree.h

#ifndef __AVLTREE__
#define __AVLTREE__

#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include "nodestack.h"

#define Type int
#define FALSE 0
#define TRUE 1
#define BOOL int

typedef struct AVLNode{
  Type data;
  struct AVLNode* left;
  struct AVLNode* right;
  int bf;//平衡因子
}AVLNode;

typedef struct AVLTree{
  struct AVLNode* root;
}AVLTree;

void init_avl_tree(AVLTree* avl);
//插入节点
BOOL insert_avl(AVLTree* avl, Type t);

#endif

avl_tree.c

#include "avl_tree.h"

void init_avl_tree(AVLTree* avl){
  avl->root = NULL;
}
AVLNode* malNode(Type x){
    AVLNode* t = (AVLNode*)malloc(sizeof(AVLNode));
    assert(NULL != t);
    t->data  = x;
    t->left  = NULL;
    t->right = NULL;
    t->bf    = 0;
    return t;
}
//右旋转
void rotateR(AVLNode** t){
  AVLNode* subR = *t;
  *t = (*t)->left;
  subR->left = (*t)->right;
  (*t)->right = subR;
  (*t)->bf = 0;
  subR->bf = 0;

}
//左旋转
void rotateL(AVLNode** t){
  AVLNode* subL = *t;
  *t = (*t)->right;
  subL->right = (*t)->left;
  (*t)->left = subL;
  (*t)->bf = 0;
  subL->bf = 0;

}
//左右旋转
void rotateLR(AVLNode** t){
  AVLNode* subR = *t;
  AVLNode* subL = subR->left;
  *t = subL->right;

  subL->right = (*t)->left;
  (*t)->left = subL;
  if((*t)->bf <= 0){///??
    subL->bf = 0;
  }
  else{
    subL->bf = -1;
  }

  subR->left = (*t)->right;
  (*t)->right = subR;
  if((*t)->bf == -1){
    subR->bf = 1;//???
  }
  else{
    subR->bf = 0;//???
  }

  (*t)->bf = 0;
}
//右左旋转
void rotateRL(AVLNode** t){
  AVLNode* subL = *t;
  AVLNode* subR = subL->right;
  *t = subR->left;

  subR->left = (*t)->right;
  (*t)->right = subR;
  if((*t)->bf >= 0){
    subR->bf = 0;
  }
  else{
    subR->bf = 1;
  }

  subL->right = (*t)->left;
  (*t)->left = subL;
  if((*t)->bf == 1){
    subL->bf = -1;
  }
  else{
    subL->bf = 0;
  }

  (*t)->bf = 0;
}
//插入树的节点
BOOL insert_avl_node(AVLNode** t, Type x){
  AVLNode* p = *t;
  AVLNode* parent = NULL;

  nodestack st;
  init(&st);

  while(p != NULL){
    if(x == p->data)
      return FALSE;
    parent = p;
    push(&st, parent);
    if(x < p->data)
      p = p->left;
    else
      p = p->right;
  }
  p = malNode(x);
  //插入节点为root节点
  if(parent == NULL){
    *t = p;
    return TRUE;
  }
  //插入节点不是root节点
  if(x < parent->data)
    parent->left = p;
  else
    parent->right = p;

  //调整BF
  while(length(&st) != 0){
    parent = getTop(&st);
    pop(&st);
    if(parent->left == p){
      parent->bf--;
    }
    else{
      parent->bf++;
    }

    if(parent->bf == 0){
      break;
    }
    if(parent->bf == 1 || parent->bf == -1){
      p = parent;
    }
    else{
      //旋转树,让树变成平衡树
      int flag = (parent->bf < 0) ? -1 : 1;
      //符号相同,说明是一条直线,不是折线,所以单旋转
      if(p->bf == flag){
    //因为是撇/,所以右旋转
    if(flag == -1){
      rotateR(&parent);
    }
    //因为是捺\,所以左旋转
    else{
      rotateL(&parent);
    }
      }
      //符号不同,说明是折线,所以双旋转
      else{
    //折线的角指向右>
    if(flag == 1){
      rotateRL(&parent);
    }
    //折线的角指向左<
    else{
      rotateLR(&parent);
    }
      }
      break;
    }
  }

  if(length(&st) == 0){
    *t = parent;
  }
  else{
    AVLNode* q = getTop(&st);
    if(q->data > parent->data){
      q->left = parent;
    }
    else{
      q->right = parent;
    }
  }

  clear(&st);
  return TRUE;
}
//插入节点
BOOL insert_avl(AVLTree* avl, Type t){
  return insert_avl_node(&avl->root, t);
}

avl_treemain.c

#include "avl_tree.h"

int main(){
  AVLTree avl;
  init_avl_tree(&avl);

  //Type ar[] = {13,24,37,90,53};
  //Type ar[] = {30,20,10};
  //Type ar[] = {30,20,40,10,25,5,22,28,21};
  //Type ar[] = {30,20,10};
  //Type ar[] = {50,40,60,10,45,70,5,30,20,12};
  Type ar[] = {30,20,50,10,40,70,60,80,55};

  int n = sizeof(ar) / sizeof(Type);
  for(int i = 0; i < n; ++i){
    insert_avl(&avl, ar[i]);
  }
  return 0;
}

完整代码

编译方法:g++ -g nodestack.c avl_tree.c avl_treemain.c

原文地址:https://www.cnblogs.com/xiaoshiwang/p/9477927.html

时间: 2024-10-03 19:04:26

平衡二叉树(Balanced Binary Tree 或 Height-Balanced Tree)又称AVL树的相关文章

数据结构与算法系列----平衡二叉树(AVL树)

一:背景 平衡二叉树(又称AVL树)是二叉查找树的一个进化体,由于二叉查找树不是严格的O(logN),所以引入一个具有平衡概念的二叉树,它的查找速度是O(logN).所以在学习平衡二叉树之前,读者需要了解二叉查找树的实现,具体链接:二叉查找树 那么平衡是什么意思?我们要求对于一棵二叉查找树 ,它的每一个节点的左右子树高度之差不超过1.(对于树的高度的约定:空节点高度是0:叶子节点高度是1.)例如下图: 如果我们的二叉查找树是不平衡该怎么办?进行旋转.经过分析发现,出现不平衡无外乎四种情况,下面我

leetCode 110. Balanced Binary Tree 平衡二叉树

110. Balanced Binary Tree Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. 题目大意: 判断一

[CareerCup] 4.1 Balanced Binary Tree 平衡二叉树

4.1 Implement a function to check if a binary tree is balanced. For the purposes of this question, a balanced tree is defined to be a tree such that the heights of the two subtrees of any node never differ by more than one. LeetCode上的原题,请参见我之前的博客Bala

AVL平衡二叉树的各种问题(Balanced Binary Tree)

AVL树或者是一棵空树,或者是具有以下性质的非空二叉搜索树: 1. 任一结点的左.右子树均为AVL树: 2.根结点左.右子树高度差的绝对值不超过1. 1.声明 #include<iostream> #include<cstdio> #include<queue> using namespace std; typedef int ElementType; typedef struct AVLNode * AVLTree; //AVL树类型 struct AVLNode{

[LeetCode][JavaScript]Balanced Binary Tree

Balanced Binary Tree Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. https://leetco

[leetcode]Balanced Binary Tree @ Python

原题地址:http://oj.leetcode.com/problems/balanced-binary-tree/ 题意:判断一颗二叉树是否是平衡二叉树. 解题思路:在这道题里,平衡二叉树的定义是二叉树的任意节点的两颗子树之间的高度差小于等于1.这实际上是AVL树的定义.首先要写一个计算二叉树高度的函数,二叉树的高度定义为:树为空时,高度为0.然后递归求解:树的高度 = max(左子树高度,右子树高度)+1(根节点要算上).高度计算函数实现后,递归求解每个节点的左右子树的高度差,如果有大于1的

LeetCode: Balanced Binary Tree [110]

[题目] Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. [题意] 判断二叉树是否是平衡二叉树 [思路] 平衡二叉树要

[Leetcode][Tree][Balanced Binary Tree]

判断一棵树是不是平衡二叉树,之前做过,还有点印象,用一个函数返回树的高度,如果是-1的话,就说明子树不平衡. 1A很开心~ 1 /** 2 * Definition for binary tree 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 cla

LeetCode OJ - Balanced Binary Tree

判断树是否是平衡的,这道题中的平衡的概念是指任意节点的两个子树的高度相差不超过1,我用递归的方法把所有的节点的高度都计算了下,并且在计算的过程记录每个节点左右两颗子树的高度差,最后通过遍历这个高度差就可以知道是否是平衡的. 下面是AC代码: 1 /** 2 * Given a binary tree, determine if it is height-balanced. 3 * For this problem, a height-balanced binary tree is defined