二分查找樹
public class BinarySearchTree {private Node root;//查找結點public Node search(int data) {Node targetNode = root;while (targetNode!=null && targetNode.data != data) {if (data > targetNode.data) {targetNode = targetNode.right;} else {targetNode = targetNode.left;}}if(targetNode == null){System.out.println("未找到結點:" + data);} else {System.out.println("已找到結點:" + data);}return targetNode;}//中序遍歷public static void inOrderTraversal(Node node){if(node == null){return;}inOrderTraversal(node.left);System.out.print(node.data + " ");inOrderTraversal(node.right);}//插入結點public boolean insert(int data) {Node node = new Node(data);if(root == null){root = node;return true;}Node targetNode = root;while (targetNode != null) {if( data == targetNode.data){System.out.println("二叉查找樹中已有重復的結點:" + data);return false;}else if (data > targetNode.data) {if(targetNode.right == null){targetNode.right = node;return true;}targetNode = targetNode.right;}else {if(targetNode.left == null){targetNode.left = node;return true;}targetNode = targetNode.left;}}return true;}//刪除結點public boolean delete(int data) {Node targetNode = root;Node parentNode = new Node(data);//判斷待刪除結點是否存在while (targetNode.data != data) {parentNode = targetNode;if (data > targetNode.data) {targetNode = targetNode.right;} else {targetNode = targetNode.left;}if (targetNode == null) {// 沒有找到待刪除結點return false;}}// 待刪除結點沒有子節點if (targetNode.right==null && targetNode.left==null) {if (targetNode == root) {//待刪除結點是根結點root = null;} else {if (parentNode.right == targetNode) {parentNode.right = null;} else {parentNode.left = null;}}}//待刪除結點有一個子結點(右)else if(targetNode.left == null) {if(targetNode == root) {root = targetNode.right;} else if(parentNode.right == targetNode) {parentNode.right = targetNode.right;} else {parentNode.left = targetNode.right;}}//待刪除結點有一個子結點(左)else if(targetNode.right == null) {if(targetNode == root) {root = targetNode.left;} else if(parentNode.right == targetNode) {parentNode.right = targetNode.left;} else {parentNode.left = targetNode.left;}}//待刪除結點有兩個子結點else {//待刪除結點的后繼結點的父結點Node successParentNode = targetNode;//待刪除結點的后繼結點Node successNode = targetNode.right;while(successNode.left != null){successParentNode = successNode;successNode = successNode.left;}//把后繼結點復制到待刪除結點位置targetNode.data = successNode.data;//刪除后繼結點if(successParentNode.right == successNode) {successParentNode.right = successNode.right;} else {successParentNode.left = successNode.right;}}return true;}// 結點類private class Node {int data;Node right;Node left;Node(int data){this.data = data;}}public static void main(String[] args) {BinarySearchTree tree = new BinarySearchTree();int input[]= {6,3,8,2,5,7,9,1,4};for(int i=0; i<input.length; i++) {tree.insert(input[i]);}inOrderTraversal(tree.root);System.out.println();tree.search(3);tree.delete(3);tree.search(3);tree.delete(6);inOrderTraversal(tree.root);}
}
AVL樹
import java.util.LinkedList;
import java.util.Queue;public class AVLTree {private TreeNode root;/** 獲取樹的高度*/private int height(TreeNode node) {if (node != null)return node.height;return 0;}public int height() {return height(root);}//查找結點public TreeNode search(TreeNode node, int data) {while (node!=null) {if (data < node.data)node = node.left;else if (data > node.data)node = node.right;elsereturn node;}return node;}//左左局面旋轉private TreeNode leftLeftRotation(TreeNode node) {//leftChildNode 對應示意圖中的結點BTreeNode leftChildNode = node.left;node.left = leftChildNode.right;leftChildNode.right = node;//刷新結點A和結點B的高度node.height = Math.max(height(node.left), height(node.right)) + 1;leftChildNode.height = Math.max(height(leftChildNode.left), node.height) + 1;//返回旋轉后的父結點return leftChildNode;}//右右局面旋轉private TreeNode rightRightRotation(TreeNode node) {//rightChildNode 對應示意圖中的結點BTreeNode rightChildNode = node.right;node.right = rightChildNode.left;rightChildNode.left = node;//刷新結點A和結點B的高度node.height = Math.max(height(node.left), height(node.right)) + 1;rightChildNode.height = Math.max(height(rightChildNode.right), node.height) + 1;//返回旋轉后的父結點return rightChildNode;}//左右局面旋轉private TreeNode leftRightRotation(TreeNode node) {//先做左旋node.left = rightRightRotation(node.left);//再做右旋return leftLeftRotation(node);}//右左局面旋轉private TreeNode rightLeftRotation(TreeNode node) {//先做右旋node.right = leftLeftRotation(node.right);//再做左旋return rightRightRotation(node);}//插入結點public void insert(int data) {root = insert(root, data);}//插入結點詳細過程(遞歸)private TreeNode insert(TreeNode node, int data) {if (node == null) {node = new TreeNode(data);} else {if (data < node.data) {//新結點小于當前結點,選擇當前結點的左子樹插入node.left = insert(node.left, data);// 插入節點后,若AVL樹失去平衡,則進行相應的調節。if (node.getBalance() == 2) {if (data < node.left.data) {node = leftLeftRotation(node);} else {node = leftRightRotation(node);}}} else if (data > node.data) {//新結點大于當前結點,選擇當前結點的右子樹插入node.right = insert(node.right, data);// 插入節點后,若AVL樹失去平衡,則進行相應的調節。if (node.getBalance() == -2) {if (data > node.right.data) {node = rightRightRotation(node);} else {node = rightLeftRotation(node);}}} else {System.out.println("AVL樹中已有重復的結點!");}}//刷新結點的高度node.height = Math.max(height(node.left), height(node.right)) + 1;return node;}//刪除結點public void remove(int data) {TreeNode deletedNode;if ((deletedNode = search(root, data)) != null)root = remove(root, deletedNode);}//刪除結點詳細過程(遞歸)private TreeNode remove(TreeNode node, TreeNode deletedNode) {// 根為空 或者 沒有要刪除的節點,直接返回null。if (node==null || deletedNode==null)return null;if (deletedNode.data < node.data){//待刪除結點小于當前結點,在當前結點的左子樹繼續執行node.left = remove(node.left, deletedNode);// 刪除節點后,若AVL樹失去平衡,則進行相應的調節。if (height(node.right) - height(node.left) == 2) {TreeNode r = node.right;if (height(r.left) > height(r.right))node = rightLeftRotation(node);elsenode = rightRightRotation(node);}} else if (deletedNode.data > node.data) {//待刪除結點大于當前結點,在當前結點的右子樹繼續執行node.right = remove(node.right, deletedNode);// 刪除節點后,若AVL樹失去平衡,則進行相應的調節。if (height(node.left) - height(node.right) == 2) {TreeNode l = node.left;if (height(l.right) > height(l.left))node = leftRightRotation(node);elsenode = leftLeftRotation(node);}} else {// tree的左右孩子都非空if ((node.left!=null) && (node.right!=null)) {if (height(node.left) > height(node.right)) {// 如果node的左子樹比右子樹高,找出左子樹最大結點賦值給Node,并刪除最小結點TreeNode max = maximum(node.left);node.data = max.data;node.left = remove(node.left, max);} else {// 如果node的右子樹比左子樹高,找出右子樹最小結點賦值給Node,并刪除最小結點TreeNode min = minimum(node.right);node.data = min.data;node.right = remove(node.right, min);}} else {node = (node.left!=null) ? node.left : node.right;}}node.height = Math.max(height(node.left), height(node.right)) + 1;return node;}//找出結點node為根的子樹的最大節點private TreeNode maximum(TreeNode node) {if (node == null)return null;while(node.right != null)node = node.right;return node;}//找出結點node為根的子樹的最小節點private TreeNode minimum(TreeNode node) {if (node == null)return null;while(node.left != null)node = node.left;return node;}//中序遍歷public static void inOrderTraversal(TreeNode node) {if(node != null) {inOrderTraversal(node.left);System.out.print(node.data+" ");inOrderTraversal(node.right);}}//層序遍歷public static void levelOrderTraversal(TreeNode root){Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while(!queue.isEmpty()){TreeNode node = queue.poll();System.out.print(node.data+" ");if(node.left != null){queue.offer(node.left);}if(node.right != null){queue.offer(node.right);}}}class TreeNode {int data;int height;TreeNode left;TreeNode right;public TreeNode(int data) {this.data = data;this.height = 0;}//獲得結點的平衡因子public int getBalance(){int left = (this.left==null ? 0:this.left.height);int right = (this.right==null ? 0:this.right.height);return left - right;}}public static void main(String[] args) {AVLTree tree = new AVLTree();int input[]= {5,3,7,2,4,6,9,1};for(int i=0; i<input.length; i++) {tree.insert(input[i]);}System.out.println("中序遍歷: ");inOrderTraversal(tree.root);System.out.println();System.out.println("層序遍歷: ");levelOrderTraversal(tree.root);System.out.println();System.out.printf("高度: %d\n", tree.height());int deletedData = 3;System.out.printf("刪除根節點: %d\n", deletedData);tree.remove(deletedData);System.out.println("中序遍歷: ");inOrderTraversal(tree.root);System.out.println();System.out.println("層序遍歷: ");levelOrderTraversal(tree.root);System.out.println();System.out.printf("高度: %d\n", tree.height());}
}
紅黑樹
import java.util.LinkedList;
import java.util.Queue;public class RedBlackTree {TreeNode root;final static boolean RED = true;final static boolean BLACK = false;//查找結點public TreeNode search(int data) {TreeNode tmp = root;while (tmp != null) {if (tmp.data == data)return tmp;else if (tmp.data > data)tmp = tmp.left;elsetmp = tmp.right;}return null;}//插入結點public boolean insert(int data) {TreeNode node = new TreeNode(data);//局面1:新結點位于樹根,沒有父結點。if (root == null) {root = node;node.color = BLACK;return true;}TreeNode targetNode = root;while (targetNode != null) {if( data == targetNode.data){System.out.println("紅黑樹中已有重復的結點:" + data);return false;} else if (data > targetNode.data) {if(targetNode.right == null){targetNode.right = node;node.parent = targetNode;insertAdjust(node);return true;}targetNode = targetNode.right;} else {if(targetNode.left == null){targetNode.left = node;node.parent = targetNode;insertAdjust(node);return true;}targetNode = targetNode.left;}}return true;}//插入后自我調整private void insertAdjust(TreeNode node) {//創建父結點和祖父結點指針TreeNode parent, grandParent;//局面3的調整有可能引發后續的一系列調整,所以使用while循環。while (node.parent != null && node.parent.color == RED) {parent = node.parent;grandParent = parent.parent;if (grandParent.left == parent) {TreeNode uncle = grandParent.right;//局面3:新結點的父結點和叔叔結點都是紅色。if (uncle != null && uncle.color == RED) {parent.color = BLACK;uncle.color = BLACK;grandParent.color = RED;node = grandParent;continue;}//局面4:新結點的父結點是紅色,叔叔結點是黑色或者沒有叔叔,且新結點是父結點的右孩子,父結點是祖父結點的左孩子。if (node == parent.right) {leftRotate(parent);TreeNode tmp = node;node = parent;parent = tmp;}//局面5:新結點的父結點是紅色,叔叔結點是黑色或者沒有叔叔,且新結點是父結點的左孩子,父結點是祖父結點的左孩子。parent.color = BLACK;grandParent.color = RED;rightRotate(grandParent);} else {TreeNode uncle = grandParent.left;//局面3(鏡像):新結點的父結點和叔叔結點都是紅色。if (uncle != null && uncle.color == RED) {parent.color = BLACK;uncle.color = BLACK;grandParent.color = RED;node = grandParent;continue;}//局面4(鏡像):新結點的父結點是紅色,叔叔結點是黑色或者沒有叔叔,且新結點是父結點的左孩子,父結點是祖父結點的右孩子。if (node == parent.left) {rightRotate(parent);TreeNode tmp = node;node = parent;parent = tmp;}//局面5(鏡像):新結點的父結點是紅色,叔叔結點是黑色或者沒有叔叔,且新結點是父結點的右孩子,父結點是祖父結點的右孩子。parent.color = BLACK;grandParent.color = RED;leftRotate(grandParent);}}//經過局面3的調整,有可能把根結點變為紅色,此時再變回黑色即可。if(root.color == RED){root.color = BLACK;}}//刪除節點public void remove(int key) {remove(search(key));}//刪除節點詳細邏輯private void remove(TreeNode node) {TreeNode targetNode = node;if (node == null)return;//第一步:如果待刪除結點有兩個非空的孩子結點,轉化成待刪除結點只有一個孩子(或沒有孩子)的情況。if (node.left != null && node.right != null) {//待刪除結點的后繼結點TreeNode successNode = targetNode.right;while(successNode.left != null) {successNode = successNode.left;}if(targetNode == root) {root = successNode;}//把后繼結點復制到待刪除結點位置targetNode.data = successNode.data;remove(successNode);return;}//第二步:根據待刪除結點和其唯一子結點的顏色,分情況處理。TreeNode successNode = node.left!= null ? node.left : node.right;TreeNode parent = node.parent;if (parent == null) {//子情況1,被刪除結點是紅黑樹的根結點:root = successNode;if (successNode != null)successNode.parent = null;} else {if (successNode != null)successNode.parent = parent;if (parent.left == node)parent.left = successNode;else {parent.right = successNode;}}if (node.color == BLACK )//第三步:遇到雙黑結點,在子結點頂替父結點之后,分成6種子情況處理。removeAdjust(parent, successNode);}//刪除結點后的自我調整private void removeAdjust(TreeNode parent, TreeNode node) {while ((node == null || node.color == BLACK) && node != root) {if (parent.left == node) {//node的兄弟節點TreeNode sibling = parent.right;//子情況3,node的兄弟結點是紅色:if (sibling != null && sibling.color == RED) {parent.color = RED;sibling.color = BLACK;leftRotate(parent);sibling = parent.right;}if (sibling == null || ((sibling.left == null || sibling.left.color == BLACK) && (sibling.right == null || sibling.right.color == BLACK))) {//子情況2(鏡像),node的父結點是黑色,兄弟和侄子結點是黑色:if(parent.color == BLACK){sibling.color = RED;node = parent;parent = node.parent;continue;}//子情況4(鏡像),node的父結點是紅色,兄弟和侄子結點是黑色:else {sibling.color = RED;break;}}//子情況5,node的父結點隨意,兄弟結點是黑色右孩子,左侄子結點是紅色,右侄子結點是黑色:if (sibling.left == null || sibling.color == RED) {sibling.left.color = BLACK;sibling.color = RED;rightRotate(sibling);sibling = sibling.parent;}//子情況6,結點2的父結點隨意,兄弟結點B是黑色右孩子,右侄子結點是紅色:sibling.color = parent.color;parent.color = BLACK;sibling.right.color = BLACK;leftRotate(parent);node = root; //跳出循環} else {//node的兄弟節點TreeNode sibling = parent.left;//子情況3(鏡像),node的兄弟結點是紅色:if (sibling != null && sibling.color == RED) {parent.color = RED;sibling.color = BLACK;rightRotate(parent);sibling = parent.left;}if (sibling == null || ((sibling.left == null || sibling.left.color == BLACK) && (sibling.right == null || sibling.right.color == BLACK))) {//子情況2(鏡像),node的父結點是黑色,兄弟和侄子結點是黑色:if(parent.color == BLACK){sibling.color = RED;node = parent;parent = node.parent;continue;}//子情況4(鏡像),node的父結點是紅色,兄弟和侄子結點是黑色:else {sibling.color = RED;break;}}//子情況5(鏡像),node的父結點隨意,兄弟結點是黑色左孩子,右侄子結點是紅色,左侄子結點是黑色:if (sibling.right == null || sibling.right.color == RED) {sibling.right.color = BLACK;sibling.color = RED;leftRotate(sibling);sibling = sibling.parent;}//子情況6(鏡像),結點2的父結點隨意,兄弟結點是黑色左孩子,左侄子結點是紅色:sibling.color = parent.color;parent.color = BLACK;sibling.left.color = BLACK;rightRotate(parent);node = root; //跳出循環}}if (node != null) {node.color = BLACK;}}//左旋轉private void leftRotate(TreeNode node) {TreeNode right = node.right;TreeNode parent = node.parent;if (parent == null) {root = right;right.parent = null;} else {if (parent.left != null && parent.left == node) {parent.left = right;} else {parent.right = right;}right.parent = parent;}node.parent = right;node.right = right.left;if (right.left != null) {right.left.parent = node;}right.left = node;}//右旋轉private void rightRotate(TreeNode node) {TreeNode left = node.left;TreeNode parent = node.parent;if (parent == null) {root = left;left.parent = null;} else {if (parent.left != null && parent.left == node) {parent.left = left;} else {parent.right = left;}left.parent = parent;}node.parent = left;node.left = left.right;if (left.right != null) {left.right.parent = node;}left.right = node;}//中序遍歷public static void inOrderTraversal(TreeNode node) {if(node != null) {inOrderTraversal(node.left);System.out.print(node);inOrderTraversal(node.right);}}//層序遍歷public static void levelOrderTraversal(TreeNode root){Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while(!queue.isEmpty()){TreeNode node = queue.poll();System.out.print(node);if(node.left != null){queue.offer(node.left);}if(node.right != null){queue.offer(node.right);}}}class TreeNode {int data;boolean color;TreeNode left;TreeNode right;TreeNode parent;public TreeNode(int data) {this.data = data;this.color = RED;}@Overridepublic String toString() {return data + (color?"(red)":"(black)") + " " ;}}public static void main(String[] args) {RedBlackTree rbTree = new RedBlackTree();int input[]= {13,8,17,1,11,15,25,6,22,27};for(int i=0; i<input.length; i++) {rbTree.insert(input[i]);}rbTree.remove(8);System.out.println("中序遍歷: ");inOrderTraversal(rbTree.root);System.out.println();System.out.println("層序遍歷: ");levelOrderTraversal(rbTree.root);System.out.println();}
}
總結
以上是生活随笔為你收集整理的《漫画算法2》源码整理-1 二分查找树 AVL树 红黑树的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。