红黑树 java代码实现
生活随笔
收集整理的這篇文章主要介紹了
红黑树 java代码实现
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 代碼實(shí)現(xiàn)
- 節(jié)點(diǎn)實(shí)現(xiàn)類
- 紅黑樹(shù)實(shí)現(xiàn)
- 單元測(cè)試
代碼實(shí)現(xiàn)
節(jié)點(diǎn)實(shí)現(xiàn)類
package csdn.dreamzuora.tree;/*** Title:* Description:** @version 1.0* @author: weijie* @date: 2020/10/19 13:30*/ public interface Node { } package csdn.dreamzuora.tree;import java.io.Serializable;/*** Title:* Description:** @version 1.0* @author: weijie* @date: 2020/10/19 13:27*/ public abstract class AbstractNode<T, E> implements Node, Serializable {private static final long serialVersionUID = -2321782309212147194L;/*** 數(shù)據(jù)域*/T data;/*** 左孩子*/E left;/*** 右孩子*/E right;public AbstractNode() {}public AbstractNode(T data) {this.data = data;}public T getData() {return data;}public void setData(T data) {this.data = data;}public E getLeft() {return left;}public void setLeft(E left) {this.left = left;}public E getRight() {return right;}public void setRight(E right) {this.right = right;} } package csdn.dreamzuora.tree;/*** Title: 紅黑樹(shù)節(jié)點(diǎn)* Description:** @version 1.0* @author: weijie* @date: 2020/10/21 14:36*/ public class RedBlackNode extends AbstractNode<Integer, RedBlackNode> {/*** 紅黑樹(shù)節(jié)點(diǎn)顏色標(biāo)記*/boolean isBlack;/*** 紅黑樹(shù)父親節(jié)點(diǎn)*/RedBlackNode parent;public RedBlackNode(Integer data) {super(data);//默認(rèn)為紅色this.isBlack = false;}public boolean isBlack() {return isBlack;}public void setBlack(boolean black) {isBlack = black;}public RedBlackNode getParent() {return parent;}public void setParent(RedBlackNode parent) {this.parent = parent;}@Overridepublic String toString() {return "RedBlackNode{" +"isBlack=" + isBlack +", data=" + data +'}';} }紅黑樹(shù)實(shí)現(xiàn)
package csdn.dreamzuora.tree;import java.util.List;/*** Title: 樹(shù)接口* Description:** @version 1.0* @author: weijie* @date: 2020/10/16 14:56*/ public interface Tree<T,E> {/*** 構(gòu)建樹(shù)* @param dataList*/void createTree(List<T> dataList);/*** 添加節(jié)點(diǎn)* @param data*/E addNode(E tree, T data);/*** 刪除節(jié)點(diǎn)* @param tree* @param node*/void deleteNode(E tree, E node);/*** 前序遍歷:根節(jié)點(diǎn)->左節(jié)點(diǎn)->右節(jié)點(diǎn)*/void preOrder(List<T> list, E node);/*** 中序遍歷:左節(jié)點(diǎn)->根節(jié)點(diǎn)->右節(jié)點(diǎn)* @return*/void inOrder(List<T> list, E node);/*** 后序遍歷:左節(jié)點(diǎn)->右節(jié)點(diǎn)->根節(jié)點(diǎn)*/void laOrder(List<T> list, E node);/*** 廣度優(yōu)先遍歷:層序遍歷* @param list* @param node*/void bfs(List<T> list, E node);} package csdn.dreamzuora.tree;import java.io.Serializable; import java.util.List;/*** Title: 二叉樹(shù)抽象類* Description:** @version 1.0* @author: weijie* @date: 2020/10/16 14:57*/ public abstract class AbstractTree<T, E> implements Tree<T, E>, Serializable {private static final long serialVersionUID = -8046156919125106629L;/*** 根節(jié)點(diǎn)*/E root;@Overridepublic void createTree(List<T> dataList) {for (T data : dataList){addNode(root, data);}}void addNode(T data){};} package csdn.dreamzuora.tree;import java.util.LinkedList; import java.util.List;/*** Title: 紅黑樹(shù)* Description:* 規(guī)則:* 1.每個(gè)節(jié)點(diǎn)不是紅色就是黑色* 2.每個(gè)根節(jié)點(diǎn)是黑色* 3.每個(gè)葉子節(jié)點(diǎn)就是黑色的空節(jié)點(diǎn)* 4.如果一個(gè)節(jié)點(diǎn)是紅色的,則它的子節(jié)點(diǎn)必須是黑色的(父子不能同為紅)* 5.平衡的關(guān)鍵字:從任一節(jié)點(diǎn)到其每個(gè)葉子的所有路徑都包含相同的黑色的節(jié)點(diǎn)* 6.新插入節(jié)點(diǎn)默認(rèn)為紅色,插入后需要校驗(yàn)紅黑樹(shù)是否符合規(guī)則,不符合則需要進(jìn)行平衡** 再平衡涉及到:左旋、右旋、顏色反轉(zhuǎn)** 紅黑樹(shù)插入分為五種情況:** 1.新節(jié)點(diǎn)(A)位于樹(shù)根,沒(méi)有父節(jié)點(diǎn)* 直接讓新節(jié)點(diǎn)變成黑色,規(guī)則二得到滿足,同時(shí),黑色的根節(jié)點(diǎn)使得每條路徑上的黑色節(jié)點(diǎn)數(shù)目都增加1,所以* 并沒(méi)有打破規(guī)則5* A(紅) -> A(黑)* 1 2 1 2*** 2.新節(jié)點(diǎn)(B)的父節(jié)點(diǎn)是黑色* 新插入的紅色結(jié)點(diǎn)B并沒(méi)有打破紅黑樹(shù)的規(guī)則,所以不需要做任何調(diào)整* A(黑)* B(紅) 3* 1 2*** 3.新節(jié)點(diǎn)(D)的父節(jié)點(diǎn)和叔叔節(jié)點(diǎn)都是紅色* A(黑) A(黑) A(紅)* B(紅) C(紅) -> B(黑) C(紅) -> ... ->B(黑) c(黑)* D(紅) 3 4 5 D(紅) D(紅)* 1 2*經(jīng)過(guò)上面的調(diào)整,這一局部重新符合了紅黑樹(shù)的規(guī)則* 4.新節(jié)點(diǎn)(D)的父節(jié)點(diǎn)是紅色,叔叔節(jié)點(diǎn)是黑色或者沒(méi)有叔叔,且新節(jié)點(diǎn)是父節(jié)點(diǎn)的右孩子,父節(jié)點(diǎn)(B)是祖父節(jié)點(diǎn)的左孩子* 我們以節(jié)點(diǎn)B為軸,做一次左旋,使得節(jié)點(diǎn)D成為父節(jié)點(diǎn),原來(lái)的父節(jié)點(diǎn)B成為D的左孩子* A(黑) A(黑)* B(紅) C(黑) -> D(紅) C(黑)* 1 D(紅) 4 5 B(紅) 3 4 5* 2 3 1 2** 5.新節(jié)點(diǎn)(D)的父節(jié)點(diǎn)是紅色,叔叔節(jié)點(diǎn)是黑色或者沒(méi)有叔叔,且新節(jié)點(diǎn)是父節(jié)點(diǎn)的左孩子,父節(jié)點(diǎn)(B)* 是祖父節(jié)點(diǎn)的左孩子* 我們以節(jié)點(diǎn)A為抽,做一次右旋轉(zhuǎn),使得節(jié)點(diǎn)B成為祖父節(jié)點(diǎn),節(jié)點(diǎn)A成為節(jié)點(diǎn)B的右孩子* A(黑) B(紅) B(黑)* B(紅) C(黑) -> D(紅) A(黑) -> D(紅) A(紅)* D 3 4 5 1 2 3 C(黑) 1 2 3 C(黑)* 1 2 4 5 4 5** 顏色反轉(zhuǎn):* 如果當(dāng)前節(jié)點(diǎn)、父節(jié)點(diǎn)、叔叔節(jié)點(diǎn)同為紅色,這種情況違反了紅黑樹(shù)的規(guī)則,需求將紅色向祖輩上傳,* 父節(jié)點(diǎn)和叔叔節(jié)點(diǎn)變?yōu)楹谏?#xff0c;爺爺節(jié)點(diǎn)變?yōu)楹?>紅色** 左旋:逆時(shí)針旋轉(zhuǎn)紅黑樹(shù)的兩個(gè)節(jié)點(diǎn),使得父節(jié)點(diǎn)被自己的右孩子取代,而自己成為自己的左孩子*** 右旋:順時(shí)針旋轉(zhuǎn)紅黑樹(shù)的兩個(gè)節(jié)點(diǎn),使得父節(jié)點(diǎn)被自己的左孩子取代,而自己成為自己的右孩子** 時(shí)間負(fù)責(zé)度:logn* @version 1.0* @author: weijie* @date: 2020/10/19 17:39*/ public class RedBlackTree extends AbstractTree<Integer, RedBlackNode> {@Overridepublic void createTree(List<Integer> dataList) {for (Integer data : dataList){addNode(data);}}@Overridepublic void addNode(Integer data) {RedBlackNode node = new RedBlackNode(data);if (root == null){//根為黑色node.setBlack(true);root = node;return ;}RedBlackNode parent = root;RedBlackNode son = null;/*** 判斷新節(jié)點(diǎn)是放在左子樹(shù)還是右子樹(shù)*/if (data <= parent.getData()){son = parent.getLeft();}else {son = parent.getRight();}/*** 對(duì)樹(shù)深度遍歷,尋找新節(jié)點(diǎn)存放的位置*/while (son != null){parent = son;if (data <= parent.getData()){son = parent.getLeft();}else {son = parent.getRight();}}/*** 節(jié)點(diǎn)插入*/if (data <= parent.getData()){parent.setLeft(node);}else {parent.setRight(node);}node.setParent(parent);/*** 自平衡*/balance(node);}@Overridepublic RedBlackNode addNode(RedBlackNode tree, Integer data) {return null;}/*** 自平衡* @param node*/private void balance(RedBlackNode node){RedBlackNode father;RedBlackNode grandFather;/*** 獲取父節(jié)點(diǎn)并判斷父節(jié)點(diǎn)是否為紅色節(jié)點(diǎn),規(guī)則:父子不同為紅*/while ((father = node.getParent()) != null && father.isBlack() == false){//獲取祖父節(jié)點(diǎn)grandFather = father.getParent();//判斷父節(jié)點(diǎn)在祖先節(jié)點(diǎn)存在的位置if (grandFather.getLeft() == father){//叔叔節(jié)點(diǎn)RedBlackNode uncle = grandFather.getRight();//如果父親、叔叔節(jié)點(diǎn)存在且都為紅,則父親、叔叔節(jié)點(diǎn)變?yōu)楹谏?/span>if (uncle != null && uncle.isBlack() == false){father.setBlack(true);uncle.setBlack(true);grandFather.setBlack(false);//接著對(duì)祖先節(jié)點(diǎn)進(jìn)行顏色反轉(zhuǎn)node = grandFather;continue;}/*** 如果沒(méi)有觸發(fā)顏色反轉(zhuǎn),需要進(jìn)行左旋、右旋操作*/if (node == father.getRight()){//左旋leftRotate(father);RedBlackNode temp = node;node = father;father = temp;}father.setBlack(true);grandFather.setBlack(false);rightRotate(grandFather);}else {RedBlackNode uncle = grandFather.getLeft();if (uncle != null && uncle.isBlack() == false){father.setBlack(true);uncle.setBlack(true);grandFather.setBlack(false);node = grandFather;continue;}if (node == father.getLeft()){rightRotate(father);RedBlackNode temp = node;node = father;father = temp;}father.setBlack(true);grandFather.setBlack(false);leftRotate(grandFather);}}root.setBlack(true);}public void leftRotate(RedBlackNode node){RedBlackNode right = node.getRight();RedBlackNode parent = node.getParent();if (parent == null){root = right;right.setParent(null);}else {if (parent.getLeft() != null && parent.getLeft() == node){parent.setLeft(right);}else {parent.setRight(right);}right.setParent(parent);}node.setParent(right);node.setRight(right.getLeft());if (right.getLeft() != null){right.getLeft().setParent(node);}right.setLeft(node);}private void rightRotate(RedBlackNode node){RedBlackNode left = node.getLeft();RedBlackNode parent = node.getParent();if (parent == null){root = left;left.setParent(null);}else {if (parent.getLeft() != null && parent.getLeft() == node){parent.setLeft(left);}else {parent.setRight(left);}left.setParent(left);}node.setParent(left);node.setLeft(left.getRight());if (left.getRight() != null){left.getRight().setParent(node);}left.setRight(node);}@Overridepublic void deleteNode(RedBlackNode root, RedBlackNode node) {}@Overridepublic void preOrder(List<Integer> showList, RedBlackNode node) {if(node == null) {return ;}//葉子if(node.getLeft() == null && node.getRight()==null){showList.add(node.getData());return ;}showList.add(node.getData());//遞歸 左孩子preOrder(showList, node.getLeft());//遞歸 右孩子preOrder(showList, node.getRight());}@Overridepublic void inOrder(List<Integer> showList, RedBlackNode node) {if(node == null) {return ;}//葉子if(node.getLeft() == null && node.getRight()==null){showList.add(node.getData());return ;}//遞歸 左孩子inOrder(showList, node.getLeft());showList.add(node.getData());//遞歸 右孩子inOrder(showList, node.getRight());}@Overridepublic void laOrder(List<Integer> showList, RedBlackNode node) {if(node == null) {return ;}//葉子if(node.getLeft() == null && node.getRight()==null){showList.add(node.getData());return ;}//遞歸 左孩子laOrder(showList, node.getLeft());//遞歸 右孩子laOrder(showList, node.getRight());showList.add(node.getData());}@Overridepublic void bfs(List<Integer> list, RedBlackNode node) {if (node == null){return;}LinkedList<RedBlackNode> queue = new LinkedList<>();queue.offer(node);while (!queue.isEmpty()){RedBlackNode child = queue.poll();list.add(child.data);if (child.left != null){queue.offer(child.left);}if (child.right != null){queue.offer(child.right);}}} }單元測(cè)試
package csdn.dreamzuora.tree;import org.junit.Before; import org.junit.Test; import org.junit.jupiter.api.Assertions;import java.util.ArrayList; import java.util.Arrays; import java.util.List;import static org.junit.Assert.*;/*** Title:* Description:** @version 1.0* @author: weijie* @date: 2020/10/22 14:31*/ public class RedBlackTreeTest {RedBlackTree RBtree = new RedBlackTree();@Beforepublic void init() {List<Integer> list = Arrays.asList(10, 5, 9, 3, 6, 7, 19, 32, 24, 17);RBtree.createTree(list);}@Testpublic void addNode(){}@Testpublic void deleteNode() {}@Testpublic void preOrder() {List<Integer> actualList = new ArrayList<>();RBtree.preOrder(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(9, 5, 3, 6, 7, 19, 10, 17, 32, 24);Assertions.assertEquals(expectList, actualList);}@Testpublic void inOrder() {List<Integer> actualList = new ArrayList<>();RBtree.inOrder(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(3, 5, 6, 7, 9, 10, 17, 19, 24, 32);Assertions.assertEquals(expectList, actualList);}@Testpublic void laOrder() {List<Integer> actualList = new ArrayList<>();RBtree.laOrder(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(3, 7, 6, 5, 17, 10, 24, 32, 19, 9);Assertions.assertEquals(expectList, actualList);}@Testpublic void bfs() {List<Integer> actualList = new ArrayList<>();RBtree.bfs(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(9, 5, 19, 3, 6, 10, 32, 7, 17, 24);Assertions.assertEquals(expectList, actualList);}@Testpublic void leftRotate(){}@Testpublic void rightRotate(){RedBlackNode node5 = new RedBlackNode(5);RedBlackNode node3 = new RedBlackNode(3);RedBlackNode node8 = new RedBlackNode(8);RedBlackNode node7 = new RedBlackNode(7);RedBlackNode node9 = new RedBlackNode(9);RBtree.root = node5;RBtree.root.left = node3;node8.left = node7;node8.right = node9;RBtree.root.right = node8;RBtree.leftRotate(RBtree.root);} }總結(jié)
以上是生活随笔為你收集整理的红黑树 java代码实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python利用jieba(textRa
- 下一篇: 【转载保存】lucene优秀文章整理