文章來自於此,經過各種查詢資料,糾結了好久的AVL樹實現總算搞定了,以下是一個動態示範的動畫avl,來源不記得了。看代碼之前務必把演算法描述看懂了,還有幾種旋轉方法(很重要,插入和刪除的平衡都靠這幾步),具體的可以看下嚴蔚敏的《資料結構與演算法》,C語言描述,裡面除了刪除沒有講,其餘的講的挺細的。這裡給的參考是wiki的。
建議看該結構的時候掌握對BST的基本操作(插入刪除)。這樣理解起來就不會怎麼吃力
package com.mars.datastructure;/** * http://dongxicheng.org/structure/avl/ * http://www.asiteof.me/2010/06/avl/ * @author hoot * */public class AVLTree4 { private static class Node { Node left; Node right; int height; int data; } private int heigth(Node t) { if(t == null){ return 0; } return t.height; } // LL private Node rightRotate(Node a) { Node b = a.left; a.left = b.right; b.right = a; a.height = max(heigth(a.left), heigth(a.right)); b.height = max(heigth(b.left), heigth(b.right)); return b; } // RR private Node leftRotate(Node a) { Node b = a.right; a.right = b.left; b.left = a; a.height = max(heigth(a.left), heigth(a.right)); b.height = max(heigth(b.left), heigth(b.right)); return b; } //LR private Node leftRightRotate(Node a){ a.left = leftRotate(a.left); return rightRotate(a); } //RL private Node rightLeftRotate(Node a){ a.right = rightRotate(a.right); return leftRotate(a); } //insert public Node insert(int data, Node t){ if(t == null){ t = newNode(data); }else if(data < t.data){ t.left = insert(data, t.left); if(heigth(t.left) - heigth(t.right) == 2){ if(data < t.left.data){ t = rightRotate(t); }else{ t = leftRightRotate(t); } } }else{ t.right = insert(data, t.right); if(heigth(t.right) - heigth(t.left) == 2){ if(data > t.right.data){ t = leftRotate(t); }else{ t = rightLeftRotate(t); } } } t.height = max(heigth(t.left), heigth(t.right)); return t; } //delete public Node delete(int data, Node t){ if(t == null){ return null; } if(t.data == data){ if(t.right == null){ t = t.left; }else{ Node head = t.right; while(head.left != null){ head = head.left; } t.data = head.data; //還記得BST樹刪除節點吧 t.right = delete(t.data, t.right); t.height = max(heigth(t.left), heigth(t.right)) + 1; } return t; }else if(t.data > data){ t.left = delete(data, t.left); }else{ t.right = delete(data, t.right); } t.height = max(heigth(t.left), heigth(t.right)); //以上只是刪除節點,但是需要保持平衡,所以還需旋轉讓其平衡以滿足AVL的性質。 //看下 if(t.left != null){ t.left = rotate(t.left); } if(t.right != null){ t.right = rotate(t.right); } return rotate(t); } private Node newNode(int data){ Node a = new Node(); a.left = a.right = null; a.height = 0; a.data = data; return a; } private int max(int heigth, int heigth2) { return heigth > heigth2 ? heigth : heigth2; } public void travel(Node root) { Node node = root; if (node == null) { return; } travel(node.left); System.out.print(node.data + " "); travel(node.right); } private Node rotate(Node t){ /*對於單個節點進行的AVL調整*/ if(heigth(t.left) - heigth(t.right) == 2){ if(heigth(t.left.left) >= heigth(t.left.right)){ t = rightRotate(t); } else{ t = leftRightRotate(t); } } if(heigth(t.right) - heigth(t.left) ==2){ if(heigth(t.right.right) >= heigth(t.right.left)){ t = leftRotate(t); } else{ t = rightLeftRotate(t); } } return t; } public static void main(String[] args) { int[] a = {0, 1, 4, 3, 8, 9, 2, 5, 7, 6, -10}; Node root = null; AVLTree4 avl = new AVLTree4(); for(int b : a){ // System.out.println("for:" + root); root = avl.insert(b, root); } System.out.println(root); avl.travel(root); avl.delete(9, root); System.out.println(); avl.travel(root); }}
鑒於旋轉的方式和名字千奇百怪,這裡給出了演算法中描述的旋轉方法和對應的名字
LL
RR
LR
RL
(插圖來源於這裡)
參考資料: http://dongxicheng.org/structure/avl/
http://www.asiteof.me/2010/06/avl/
《資料結構與演算法》嚴蔚敏
PS一句,其實嚴蔚敏的資料結構與演算法很不錯,描述了很多常用的演算法和結構,各大公司面試題所用到的知識也有很大一部分可以從中找到解決方案,所以建議在校的或者有這方面需求的,如果覺得演算法導論太厚了,可以先把嚴老的這本啃透再去啃演算法導論,珠璣編程,等演算法書籍。