package demo;
import java.util.LinkedList;
import java.util.prefs.BackingStoreException;
import org.w3c.dom.Node;
/**
* 自平衡二叉樹
*
* @author Administrator
*
* @param <K>
* @param <V>
*/
public class BSTAvl<K extends Comparable<K>, V> {
private final Node EmptyNode = null;
private Node head; // 頭結(jié)點(diǎn)
private int count;// 樹中的節(jié)點(diǎn)個(gè)數(shù)
private final static int balancerThreadhold = 2;// 樹調(diào)整閾值
/**
* 私有節(jié)點(diǎn)
*
* @author Administrator
*
* @param <K>
* @param <V>
*/
private class Node {
K key;
V value;
Node left;
Node right;
int height;
private Node(K key, V val) {
this.key = key;
this.value = val;
this.left = EmptyNode;
this.right = EmptyNode;
this.height = 1;
}
private Node(Node node) {
this.key = node.key;
this.value = node.value;
this.left = node.left;
this.right = node.right;
this.height = node.height;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{ ").append(key).append(":").append(value).append(" }");
return sb.toString();
}
}
public BSTAvl() {
head = EmptyNode;
count = 0;
}
/**
* 當(dāng)前節(jié)點(diǎn)中的元素個(gè)數(shù)
*
* @return
*/
public int size() {
return count;
}
/**
* 當(dāng)前樹是否為空
*
* @return
*/
public boolean isEmpty() {
return count == 0;
}
/**
* 添加公共方法
*
* @param key
* @param val
*/
/**
* @param key
* @param val
*/
public void insert(K key, V val) {
checkArg(key, "key is null");
head = insert(head, key, val);
}
/**
* 實(shí)際的內(nèi)部添加方法
*
* @param root
* @param key
* @param val
* @return
*/
private Node insert(Node root, K key, V val) {
if (root == EmptyNode) {
count++;
return new Node(key, val);
}
if (root.key.compareTo(key) > 0)
root.left = insert(root.left, key, val);
else if (root.key.compareTo(key) < 0)
root.right = insert(root.right, key, val);
else
root.value = val;
root = tryBalance(root);
return root;
}
private Node tryBalance(Node root) {
// 計(jì)算新的高度
root.height = 1 + Math.max(getHeight(root.left), getHeight(root.right));
// 根據(jù)平衡因子和節(jié)點(diǎn)數(shù)的高度遭垛,判斷是否需要左旋或是右旋
// LL
if (getBalanceFactor(root) > 1 && getBalanceFactor(root.left) >= 0)
return rotationRight(root);
// RR
if (getBalanceFactor(root) < -1 && getBalanceFactor(root.right) <= 0)
return rotationLeft(root);
// LR
if (getBalanceFactor(root) > 1 && getBalanceFactor(root.left) < 0) {
root.left = rotationLeft(root.left);
return rotationRight(root);
}
// RL
if (getBalanceFactor(root) < -1 && getBalanceFactor(root.right) > 0) {
root.right = rotationRight(root.right);
return rotationLeft(root);
}
return root;
}
/**
* 根據(jù)key查找指定的值公共方法
*
* @param key
* @return
*/
public V search(K key) {
return (V) search(head, key);
}
/**
* 實(shí)際的搜索方法
*
* @param root
* @param key
* @return
*/
private V search(Node root, K key) {
checkArg(key, "key is null");
if (root == EmptyNode)
return null;
if (root.key.compareTo(key) == 0)
return root.value;
else if (root.key.compareTo(key) > 0)
return (V) search(root.left, key);
else
return (V) search(root.right, key);
}
/**
* 前序遍歷
*/
public void preOrder() {
preOrder(head);
}
private void preOrder(Node root) {
if (root == EmptyNode)
return;
System.out.print(root);
preOrder(root.left);
preOrder(root.right);
}
/**
* 中序遍歷
*/
public void midOrder() {
midOrder(head);
}
private void midOrder(Node root) {
if (root == EmptyNode)
return;
midOrder(root.left);
System.out.print(root);
midOrder(root.right);
}
/**
* 后序遍歷
*/
public void postOrder() {
postOrder(head);
}
private void postOrder(Node root) {
if (root == EmptyNode)
return;
postOrder(root.left);
postOrder(root.right);
System.out.println(root);
}
/**
* 非空檢查
*
* @param key
* @param thrStr
*/
private void checkArg(Object key, String thrStr) {
if (key == null)
throw new IllegalArgumentException(thrStr);
}
/**
* 層級遍歷
*/
public void levelOrder() {
if (head == EmptyNode)
return;
LinkedList<Node> ll = new LinkedList();
ll.addLast(head);
while (!ll.isEmpty()) {
Node node = ll.removeFirst();
System.out.println(node);
if (node.left != EmptyNode)
ll.addLast(node.left);
if (node.right != EmptyNode)
ll.addLast(node.right);
}
}
/**
* 獲取最小的節(jié)點(diǎn)
*
* @return
*/
public K getMinNode() {
checkArg(head, "this tree is empty!!");
return (K) getMinNode(head).key;
}
private Node getMinNode(Node root) {
if (root.left == EmptyNode)
return root;
return getMinNode(root.left);
}
/**
* 獲取最大的節(jié)點(diǎn)
*
* @return
*/
public K getMaxNode() {
checkArg(head, "this tree is empty!!");
return (K) getMaxNode(head).key;
}
private Node getMaxNode(Node root) {
if (root.right == EmptyNode)
return root;
return getMaxNode(root.right);
}
/**
* 刪除最小的節(jié)點(diǎn)
*/
public void removeMin() {
checkArg(head, "the tree is empty");
head = removeMin(head);
}
private Node removeMin(Node root) {
if (root.left == EmptyNode) {
Node rightNode = root.right;
root = EmptyNode;
count--;
return rightNode;
}
root.left = removeMin(root.left);
return root;
}
public void removeMax() {
checkArg(head, "the tree is empty");
head = removeMax(head);
}
private Node removeMax(Node root) {
if (root.right == EmptyNode) {
Node leftNode = root.left;
root = null;
count--;
return leftNode;
}
root.right = removeMax(root.right);
return root;
}
public void remove(K key) {
head = remove(head, key);
}
/**
* 刪除指定
*
* @param root
* @param key
* @return
*/
private Node remove(Node root, K key) {
if (root == EmptyNode)
return EmptyNode;
Node retNode;
if (root.key.compareTo(key) < 0) {//
root.right = remove(root.right, key);
retNode = root;
} else if (root.key.compareTo(key) > 0) {
root.left = remove(root.left, key);
retNode = root;
} else {// equal
if (root.left == EmptyNode) {// 沒有左節(jié)點(diǎn)
Node rightNode = root.right;
root = EmptyNode;
count--;
retNode = rightNode;
} else if (root.right == EmptyNode) {// 沒有右節(jié)點(diǎn)
Node leftNode = root.right;
root = EmptyNode;
count--;
retNode = leftNode;
} else {
// 左右節(jié)點(diǎn)都存在
Node min = getMinNode(root.right);
Node s = new Node(min);
s.right = remove(root.right,s.key);
s.left = root.left;
retNode = s;
}
if (retNode == EmptyNode)
return EmptyNode;
}
retNode = tryBalance(retNode);
return retNode;
}
/**
* 獲取平衡因子
*
* @param node
* @return
*/
public int getBalanceFactor(Node node) {
checkArg(node, "節(jié)點(diǎn)為空!!");
return getHeight(node.left) - getHeight(node.right);
}
/**
* 獲取節(jié)點(diǎn)高度
*
* @param node
* @return
*/
public int getHeight(Node node) {
if (node == null)
return 0;
return node.height;
}
/**
* 節(jié)點(diǎn)左旋
*
* @param node
*/
public Node rotationLeft(Node node) {
Node x = node.right;
Node T3 = x.left;
x.left = node;
node.right = T3;
node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
return x;
}
public Node rotationRight(Node node) {
Node x = node.left;
Node T3 = x.right;
x.right = node;
node.left = T3;
node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
return x;
}
public boolean isAvl() {
return isAvl(head);
}
/**
* 判斷當(dāng)前樹是否為平衡樹
*
* @param head
* @return
*/
private boolean isAvl(Node node) {
if (node == null)
return true;
if (Math.abs(getBalanceFactor(node)) > 1)
return false;
return isAvl(node.left) && isAvl(node.right);
}
/**
* 主要的測試函數(shù)
*
* @param args
*/
public static void main(String[] args) {
BSTAvl<Integer, Object> bst = new BSTAvl();
bst.insert(1, "hello");
bst.insert(10, "hello");
bst.insert(9, "hello");
bst.insert(20, "hello");
bst.insert(11, "hello");
bst.insert(14, "hello");
bst.insert(90, "hello");
bst.insert(25, "hello");
// bst.insert(60, "hello");
bst.insert(78, "hello");
bst.midOrder();
System.out.println("");
System.out.println(bst.isAvl());
bst.remove(14);
// System.out.println("");
System.out.println(bst.isAvl());
bst.midOrder();
}
}
自平衡二叉樹
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門闽巩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钧舌,“玉大人,你說我怎么就攤上這事涎跨⊥荻常” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵隅很,是天一觀的道長撞牢。 經(jīng)常有香客問我,道長叔营,這世上最難降的妖魔是什么屋彪? 我笑而不...
- 正文 為了忘掉前任,我火速辦了婚禮审编,結(jié)果婚禮上撼班,老公的妹妹穿的比我還像新娘。我一直安慰自己垒酬,他們只是感情好砰嘁,可當(dāng)我...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勘究,像睡著了一般矮湘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上口糕,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼棠绘!你這毒婦竟也來了件相?” 一聲冷哼從身側(cè)響起再扭,我...
- 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎夜矗,沒想到半個(gè)月后泛范,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡紊撕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年罢荡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逛揩。...
- 正文 年R本政府宣布逞泄,位于F島的核電站患整,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏喷众。R本人自食惡果不足惜各谚,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望到千。 院中可真熱鬧昌渤,春花似錦、人聲如沸憔四。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽了赵。三九已至潜支,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間柿汛,已是汗流浹背冗酿。 一陣腳步聲響...
- 正文 我出身青樓,卻偏偏與公主長得像貌笨,于是被迫代替她去往敵國和親胯究。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- 1躁绸、TreeSet/TreeMap自平衡二叉樹,遵循左小右大順序存放。2净刮、遍歷二叉樹的時(shí)候有三種方式:前序遍歷:根...
- 為什么需要AVL樹剥哑? 在二叉搜索樹專題講過二叉搜索樹一定程度上可以提高搜索效率,但是當(dāng)原序列有序時(shí)淹父,依據(jù)此序列構(gòu)造...
- 題目 判斷一棵二叉樹是否是平衡二叉樹株婴。(平衡二叉樹每個(gè)節(jié)點(diǎn)的左右兩個(gè)子樹的高度差的絕對值不超過1。) 解題方法 從...
- 樹 在計(jì)算機(jī)科學(xué)中,樹(英語:tree)是一種抽象數(shù)據(jù)類型或是實(shí)現(xiàn)這種抽象數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu)递递,用來模擬具有樹狀結(jié)構(gòu)...
- 給定一個(gè)二叉樹喷橙,判斷它是否是高度平衡的二叉樹。本題中漾狼,一棵高度平衡二叉樹定義為:一個(gè)二叉樹每個(gè)節(jié)點(diǎn) 的左右兩個(gè)子樹...