主文章(数据结构的索引目录—进不去就说明我还没写完) https://blog.csdn.net/grd_java/article/details/122377505
模拟数据结构的网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
源码(码云):https://gitee.com/yin_zhipeng/data_structures_and_algorithms_in_java.git
平衡二叉树,就是更完善的二叉排序树,代码也是在二叉排序基础上添加了一些逻辑
平衡二叉树(AVL),又名平衡二叉搜索树,保证查询效率较高 它是一课空树或它的左右两个子树的高度差的绝对值小于等于1
,并且左右两个子树都是一课平衡二叉树。满足这些特点就是平衡二叉树。(下图就是一课树,右子树高度比左子树高2,不满足,所以进行左旋转操作,后面会讲) 常用实现算法有红黑树、AVL算法、替罪羊树、Treap、伸展树等
当我们要将一个递增的序列转换成二叉排序树时,那么会变成一个效率很低的单链表,因为需要判断左右子树 而平衡二叉树可以解决此类问题
左旋转(以右子树比左子树高度,高1以上,比如2,就需要左旋转,反之右旋转)
某些序列,无法通过左旋转,或右旋转,转变为平衡二叉树,此时需要双旋转
class AVL {
Node root;
class Node {
int val;
Node parent;
Node left;
Node right;
int size;
int height;
public Node ( int val) {
this ( val, null ) ;
}
public Node ( int val, Node parent) {
this ( val, parent, null , null ) ;
}
public Node ( int val, Node parent, Node left, Node right) {
this . val = val;
this . parent = parent;
this . left = left;
this . right = right;
this . height = 0 ;
this . size = 1 ;
}
}
public AVL ( List < Integer > vals) {
if ( vals != null ) {
this . root = build ( vals, 0 , vals. size ( ) - 1 , null ) ;
}
}
private Node build ( List < Integer > vals, int l, int r, Node parent) {
int m = ( l + r) >> 1 ;
Node node = new Node ( vals. get ( m) , parent) ;
if ( l <= m - 1 ) {
node. left = build ( vals, l, m - 1 , node) ;
}
if ( m + 1 <= r) {
node. right = build ( vals, m + 1 , r, node) ;
}
recompute ( node) ;
return node;
}
public int kthSmallest ( int k) {
Node node = root;
while ( node != null ) {
int left = getSize ( node. left) ;
if ( left < k - 1 ) {
node = node. right;
k -= left + 1 ;
} else if ( left == k - 1 ) {
break ;
} else {
node = node. left;
}
}
return node. val;
}
public void insert ( int v) {
if ( root == null ) {
root = new Node ( v) ;
} else {
Node node = subtreeSearch ( root, v) ;
boolean isAddLeft = v <= node. val;
if ( node. val == v) {
if ( node. left != null ) {
node = subtreeLast ( node. left) ;
isAddLeft = false ;
} else {
isAddLeft = true ;
}
}
Node leaf = new Node ( v, node) ;
if ( isAddLeft) {
node. left = leaf;
} else {
node. right = leaf;
}
rebalance ( leaf) ;
}
}
public boolean delete ( int v) {
if ( root == null ) {
return false ;
}
Node node = subtreeSearch ( root, v) ;
if ( node. val != v) {
return false ;
}
if ( node. left != null && node. right != null ) {
Node replacement = null ;
if ( node. left. height <= node. right. height) {
replacement = subtreeFirst ( node. right) ;
} else {
replacement = subtreeLast ( node. left) ;
}
node. val = replacement. val;
node = replacement;
}
Node parent = node. parent;
delete ( node) ;
rebalance ( parent) ;
return true ;
}
private void delete ( Node node) {
if ( node. left != null && node. right != null ) {
return ;
}
Node child = node. left != null ? node. left : node. right;
if ( child != null ) {
child. parent = node. parent;
}
if ( node == root) {
root = child;
} else {
Node parent = node. parent;
if ( node == parent. left) {
parent. left = child;
} else {
parent. right = child;
}
}
node. parent = node;
}
private Node subtreeSearch ( Node node, int v) {
if ( node. val < v && node. right != null ) {
return subtreeSearch ( node. right, v) ;
} else if ( node. val > v && node. left != null ) {
return subtreeSearch ( node. left, v) ;
} else {
return node;
}
}
private void recompute ( Node node) {
node. height = 1 + Math . max ( getHeight ( node. left) , getHeight ( node. right) ) ;
node. size = 1 + getSize ( node. left) + getSize ( node. right) ;
}
private void rebalance ( Node node) {
while ( node != null ) {
int oldHeight = node. height, oldSize = node. size;
if ( ! isBalanced ( node) ) {
node = restructure ( tallGrandchild ( node) ) ;
recompute ( node. left) ;
recompute ( node. right) ;
}
recompute ( node) ;
if ( node. height == oldHeight && node. size == oldSize) {
node = null ;
} else {
node = node. parent;
}
}
}
private boolean isBalanced ( Node node) {
return Math . abs ( getHeight ( node. left) - getHeight ( node. right) ) <= 1 ;
}
private Node tallChild ( Node node) {
if ( getHeight ( node. left) > getHeight ( node. right) ) {
return node. left;
} else {
return node. right;
}
}
private Node tallGrandchild ( Node node) {
Node child = tallChild ( node) ;
return tallChild ( child) ;
}
private static void relink ( Node parent, Node child, boolean isLeft) {
if ( isLeft) {
parent. left = child;
} else {
parent. right = child;
}
if ( child != null ) {
child. parent = parent;
}
}
private void rotate ( Node node) {
Node parent = node. parent;
Node grandparent = parent. parent;
if ( grandparent == null ) {
root = node;
node. parent = null ;
} else {
relink ( grandparent, node, parent == grandparent. left) ;
}
if ( node == parent. left) {
relink ( parent, node. right, true ) ;
relink ( node, parent, false ) ;
} else {
relink ( parent, node. left, false ) ;
relink ( node, parent, true ) ;
}
}
private Node restructure ( Node node) {
Node parent = node. parent;
Node grandparent = parent. parent;
if ( ( node == parent. right) == ( parent == grandparent. right) ) {
rotate ( parent) ;
return parent;
} else {
rotate ( node) ;
rotate ( node) ;
return node;
}
}
private static Node subtreeFirst ( Node node) {
while ( node. left != null ) {
node = node. left;
}
return node;
}
private static Node subtreeLast ( Node node) {
while ( node. right != null ) {
node = node. right;
}
return node;
}
private static int getHeight ( Node node) {
return node != null ? node. height : 0 ;
}
private static int getSize ( Node node) {
return node != null ? node. size : 0 ;
}
}