BinarySearchTree
public class Node {
private Node left;
private Node right;
private Node parent;
private Integer value;
/**
* value list
*/
private List list = new ArrayList();
@Override
public String toString() {
return "Node{" +
(this.getLeft() == null ? "" : "left=" + this.getLeft().getValue()) +
(this.getRight() == null ? "" : ",right=" + this.getRight().getValue()) +
(this.getParent() == null ? "" : ",parent=" + this.getParent().getValue()) +
", value=" + this.getValue() +
(this.getList().size() == 0 ? "" : ",list=" + this.getList()) +
'}';
}
}
BinarySearchTree api
/**
* BST
* RI(Represent Invariant):
* X , left(X).value < X.value and right(X).value > X.value
* @author haofan.whf
* @version $Id: BinarySearchTree.java, v 0.1 2018 12 09 11:13 haofan.whf Exp $
*/
public class BinarySearchTree {
/**
* value Node
* T(N) = O(h)
* h ( lgN, BST , ( ) )
* @param value
* @return
*/
public Node query(Node root, int value){
if(root.getValue() < value){
if(root.getRight() != null){
return query(root.getRight(), value);
}else{
return null;
}
}else if(root.getValue() > value){
if(root.getLeft() != null){
return query(root.getLeft(), value);
}else{
return null;
}
}else{
return root;
}
}
/**
*
* , list
* T(N) = O(h) , query
* @param value
* @return
*/
public void insert(Node root, int value){
if(root.getValue() == null){
root.setValue(value);
doAfterInsert(root);
return;
}
if(root.getValue() < value){
//
if(root.getRight() == null){
// ,
Node n = createNode();
n.setParent(root);
n.setValue(value);
root.setRight(n);
doAfterInsert(n);
}else{
insert(root.getRight(), value);
}
}else if(root.getValue() > value){
if(root.getLeft() == null){
Node n = createNode();
n.setParent(root);
n.setValue(value);
root.setLeft(n);
doAfterInsert(n);
}else{
insert(root.getLeft(), value);
}
}else{
root.getList().add(value);
}
}
public Node createNode(){
return new Node();
}
/**
* @param node Node
*/
public void doAfterInsert(Node node){
}
/**
* ( value root )
* T(N) = O(h)
* @return
*/
public Node findSuccessor(Node root, int value){
Node node = query(root, value);
if(node == null){
throw new RuntimeException("can not found node=" + node);
}
return findSuccessor(node);
}
/**
* ( node , node rightSubTree , rightSubTree node.value parent)
* T(N) = O(h)
* @return
*/
public Node findSuccessor(Node node){
if(node.getRight() != null){
return query(node, findMin(node.getRight()));
}else{
int value = node.getValue();
boolean foundSuccessor = false;
while(node.getParent() != null){
if(node.getParent().getValue() > value){
foundSuccessor = true;
break;
}
node = node.getParent();
}
return foundSuccessor ? node : null;
}
}
/**
*
* list
*
* T(N) = O(h)
* @param root
* @param value
* @return
*/
public void delete(Node root, int value){
Node node = query(root, value);
if(node == null){
return;
}
int leftOrRight = leftOrRight(node);
if(node.getRight() == null && node.getLeft() == null){
// ,
doBeforeDelete(node);
if(leftOrRight == -1){
node.getParent().setLeft(null);
}else if(leftOrRight == 1){
node.getParent().setRight(null);
}else{
// ,
root = null;
}
}else if(node.getRight() == null && node.getLeft() != null){
//
doBeforeDelete(node);
node.getLeft().setParent(node.getParent());
if(leftOrRight == -1){
node.getParent().setLeft(node.getLeft());
}else if(leftOrRight == 1){
node.getParent().setRight(node.getLeft());
}else{
//
node.getLeft().setParent(null);
root = node.getLeft();
}
}else if(node.getRight() != null && node.getLeft() == null){
//
doBeforeDelete(node);
node.getRight().setParent(node.getParent());
if(leftOrRight == -1){
node.getParent().setLeft(node.getRight());
}else if(leftOrRight == 1){
node.getParent().setRight(node.getRight());
}else{
//
node.getRight().setParent(null);
root = node.getRight();
}
}else{
Node successor = findSuccessor(node);
swap(successor, node);
// node successor
// , ,
delete(successor, successor.getValue());
}
}
/**
* @param node Node
*/
public void doBeforeDelete(Node node){
}
/**
* node ( , )
* @param node1
* @param node2
*/
public void swap(Node node1, Node node2){
int value1 = node1.getValue();
List list1 = node1.getList();
int value2 = node2.getValue();
List list2 = node2.getList();
node1.setValue(value2);
node2.setValue(value1);
node1.setList(list2);
node2.setList(list1);
}
/**
* node parent /
* @param node
* @return
*/
public int leftOrRight(Node node){
if(node.getParent() == null){
//
return 0;
}else{
if(node.getParent().getLeft() != null
&& node.getParent().getLeft().getValue() == node.getValue()){
//
return -1;
}else if(node.getParent().getRight() != null
&& node.getParent().getRight().getValue() == node.getValue()){
//
return 1;
}else {
throw new RuntimeException("impossible!");
}
}
}
/**
* ,
* T(N) = O(h)
* @param root
* @return
*/
public int findMax(Node root){
if(root.getRight() != null){
return findMax(root.getRight());
}else{
return root.getValue();
}
}
/**
* ,
* T(N) = O(h)
* @param root
* @return
*/
public int findMin(Node root){
if(root.getLeft() != null){
return findMin(root.getLeft());
}else{
return root.getValue();
}
}
/**
* BST
* T(N) = O(N)
*
* @param root
*/
public void checkRI(Node root){
if(root == null){
return;
}
if(root.getRight() != null){
if(root.getValue() > root.getRight().getValue()){
System.err.println(root);
throw new RuntimeException("it's not a bst");
}
}
if(root.getLeft() != null){
if(root.getValue() < root.getLeft().getValue()){
System.err.println(root);
throw new RuntimeException("it's not a bst");
}
}
checkRI(root.getRight());
checkRI(root.getLeft());
}
public class BSTTest {
@Test
public void bstNormal(){
BinarySearchTree bst = new BinarySearchTree();
int[] array = new int[]{3,5,6,4,2};
Node root = new Node();
for (int i = 0; i < array.length; i++) {
bst.insert(root, array[i]);
}
bst.checkRI(root);
Assert.assertTrue(bst.query(root, 6).getValue() == 6);
Assert.assertTrue(bst.findMax(root) == 6);
Assert.assertTrue(bst.findMin(root) == 2);
Assert.assertTrue(bst.findSuccessor(root, 5).getValue() == 6);
Assert.assertTrue(bst.findSuccessor(root, 6) == null);
int[] insertArray = randomArray(100);
root = new Node();
for (int i = 0; i < insertArray.length; i++) {
bst.insert(root, insertArray[i]);
bst.checkRI(root);
}
int[] deleteArray = randomArray(50);
for (int i = 0; i < deleteArray.length; i++) {
bst.delete(root, deleteArray[i]);
bst.checkRI(root);
}
}
private static int[] randomArray(int size){
Random random = new Random();
int[] array = new int[size];
for (int i = 0; i < size; i++) {
array[i] = random.nextInt(size);
}
return array;
}
}
BST 의 장점 은 어떤 조작 시간 이 든 복잡 도 는 O (h) 류 BST 구조의 장점 은 노드 에 일부 정 보 를 저장 하여 특정한 조작 을 최적화 할 수 있다 는 것 이다. 예 를 들 어 MaxMinBinary SearchTree 등 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.