데이터 구조 - 이 진 검색 트 리 (Binary SearchTree) 의 실현

이 진 트 리 는 이 진 트 리 의 확장 입 니 다.나무의 요 소 는 질서 가 있 는 것 으로 볼 수 있다.특수 한 구조 로 인해 2 분 검색 작업 에 적합 하고 찾 는 평균 시간 복잡 도 는 O (logN) 입 니 다.그러나 이것 은 하나의 링크 로 퇴화 할 수도 있 습 니 다. 이때 찾 은 최 악의 시간 복잡 도 는 O (N) 로 변 할 수 있 습 니 다.
특징.
트 리 의 임의의 노드 X 는 왼쪽 트 리 의 모든 노드 값 보다 크 고 오른쪽 트 리 의 모든 노드 값 보다 작 습 니 다.(트 리 의 요소 가 서로 다 르 고 똑 같은 요소 값 이 존재 하지 않 는 다 고 가정 합 니 다)
BinarySearchTree
이번 구현 에 서 는 트 리 에 저 장 된 요소 에 대해 Comparable 인 터 페 이 스 를 실현 해 야 한 다 는 요구 가 없습니다.Comparator 와 Comparable 인 터 페 이 스 를 동시에 결합 했다.사용 자 는 이 진 트 리 를 구성 할 때 사용자 정의 비교 기 를 입력 하거나 비교 기 를 사용 하지 않 고 저 장 된 요소 에서 Comparable 인 터 페 이 스 를 실현 할 수 있 습 니 다 (이때 Comparable 인 터 페 이 스 는 반드시 실현 되 어야 합 니 다).
구성원 변수
private BinaryNode root; //두 갈래 검색 트 리 의 뿌리 노드 private Comparator cmp; /요소 의 사용자 정의 비교 기
구조 기
두 개의 구조 기 가 있 는데 그 중 하 나 는 인삼 을 함유 한 구조 기로 사용자 정의 비교 기 에 들 어 갈 수 있다.구조 기 에 서 는 주로 나무 뿌리 노드 를 초기 화 합 니 다.
public BinarySearchTree(){
    this(null);
}

public BinarySearchTree(Comparator<T> cmp){
    this.cmp = null;
}

함수.
상용 함수
public void setComparator(Comparator<T> cmp){
    this.cmp = cmp;
}

public boolean isEmpty(){
    return root == null;
}

public void clearTree(){
    root = null;
}

내부 비교 방법 으로 두 수의 크기 를 비교 하고 결 과 를 되 돌려 줍 니 다.방법 에 서 는 사용자 정의 비교 기 가 있 는 지 여 부 를 판단 하고, 사용자 정의 비교 기 를 사용 하여 두 개의 크기 를 비교 하지 않 으 면 Comparable 인터페이스의 comparaTo 함 수 를 사용 하여 비교 합 니 다.
@SuppressWarnings("unchecked")
private int innerCompareTo(T lhs, T rhs){
    if(cmp != null)
        return cmp.compare(lhs, rhs);
    else
        return ((Comparable<T>)lhs).compareTo(rhs);
}

contains (): 트 리 에 어떤 요소 가 포함 되 어 있 는 지 찾 아 재 귀적 인 방법 으로 2 분 검색 합 니 다.2 분 검색 법: 찾 아야 할 값 x 와 현재 노드 값 을 비교 하고 노드 값 보다 작 으 면 왼쪽 하위 트 리 에서 계속 검색 합 니 다.x 가 현재 노드 보다 크 면 오른쪽 하위 트 리 에서 검색 합 니 다.루트 노드 위치 까지 반복 합 니 다. 일치 하 는 값 을 검색 하지 않 으 면 트 리 에 x 값 이 포함 되 지 않 습 니 다.
public boolean contains(T x){
    return contains(x, root);
}

private boolean contains(T x, BinaryNode<T> tree){
    if(tree == null)
        return false;
    /*     x     ,                    */
    int result = innerCompareTo(x, tree.element);
    if(result < 0)
        return contains(x, tree.left);
    else if(result > 0)
        return contains(x, tree.right);
    /* result = 0,             */
    else
        return true;
}

insert (): 요 소 를 삽입 합 니 다.모든 요 소 는 나무의 새로운 잎 노드 로 나무 에 삽입 되 어 있다.삽입 작업 의 평균 시간 복잡 도 는 O (logN) 이지 만 질서 있 는 요소 가 삽입 작업 을 하면 최 악의 상황 이 될 수 있 습 니 다. 시간 복잡 도 는 O (logN) 이 고 퇴화 된 이 진 검색 트 리 (링크 로 변 함) 를 얻 을 수 있 습 니 다. 이 럴 때 삭제 든 검색 작업 시간 복잡 도 는 O (N) 가 됩 니 다.
public void insert(T x){
    root = insert(x, root);
}

private BinaryNode<T> insert(T x, BinaryNode<T> tree){
    /*         ,             */
    if(tree == null)
        return new BinaryNode<T>(x);

    int result = innerCompareTo(x, tree.element);
    if(result < 0)
        tree.left = insert(x, tree.left);
    else if(result > 0)
        tree.right = insert(x, tree.right);
    else{
        //       ,        
    }
    return tree;
}

remove (): 요소 x 를 삭제 합 니 다.두 갈래 검색 트 리 의 삭제 작업 은 비교적 간단 하 다.삭제 할 노드 는 주로 다음 과 같은 몇 가지 상황 입 니 다. 1. 이 노드 가 존재 하지 않 고 삭제 에 실 패 했 습 니 다.2. 삭제 할 노드 가 잎 결점 이면 이 노드 를 직접 삭제 합 니 다.3. 노드 를 삭제 할 때 한 아이 가 있 습 니 다. 이 노드 를 삭제 하면 아이의 노드 를 부모 노드 에 되 돌려 주면 됩 니 다.4. 삭제 할 노드 에 두 명의 아이 가 있 는데 이런 상황 에서 상대 적 으로 복잡 하 다.일반적인 해결 방법 은 오른쪽 하위 트 리 의 최소 값 으로 노드 값 을 교체 한 다음 에 오른쪽 하위 트 리 의 최소 값 을 삭제 하면 됩 니 다 (이때 오른쪽 하위 트 리 의 최소 값 노드 에 왼쪽 아이 가 없 으 면 2, 3 상황 이 되 기 때 문 입 니 다).그러나 이런 요 소 를 삭제 하 는 방법 은 여러 번 조작 한 후에 나무의 불 균형 을 초래 할 수 있다. 즉, 오른쪽 나무의 높이 가 보편적으로 낮다.따라서 우 리 는 오른쪽 트 리 의 최소 값 을 무 작위 로 삭제 하거나 왼쪽 트 리 의 최대 값 을 삭제 하 는 방식 을 취 할 수 있다.
public void remove(T x){
    root = remove(x, root);
}

private BinaryNode<T> remove(T x, BinaryNode<T> tree){
    /*             */
    if(tree == null)
        return null;

    int result = innerCompareTo(x, tree.element);
    /*           */
    if(result < 0)
        tree.left = remove(x, tree.left);
    /*           */
    else if(result > 0)
        tree.right = remove(x, tree.right);
    /* 1.         ,      ,     
     *                          
     *                   (              ,          ( 2))
     */
    else if(tree.left != null && tree.right != null){
        tree.element = findMax();
    }
    /* 2.      ,                   
     * -             
     * -          ,        
     */
    else{
        tree = (tree.left != null) ? tree.left : tree.right; 
    }
    return tree;
}

findMin (): 최소 값 을 조회 합 니 다.트 리 의 최소 값 은 왼쪽 트 리 의 최소 요소 입 니 다.재 귀 실현 을 채택 하 다.findMax (): 최대 값 을 조회 합 니 다.트 리 의 최대 치 는 오른쪽 트 리 의 최대 요소 입 니 다.비 귀속 실현 을 채택 하 다.
public T findMin(){
    return findMin(root);
}

private T findMin(BinaryNode<T> tree){
    /*         */
    if(tree == null)
        return null;
    /*             ,             */
    else if(tree.left != null)
        return findMin(tree.left);
    /*        */
    else
        return tree.element;
}

public T findMax(){
    return findMax(root);
}

private T findMax(BinaryNode<T> tree){
    /*      */
    if(tree != null)
        /*                 ,
         * ps:   tree       ,           .
         *                 ,        !
         *    tree.right = tree.left                .
         */
        while(tree.right != null)
            tree = tree.right;
    return tree.element;
}

print (): 트 리 의 요소 값 을 순서대로 출력 합 니 다.중 서 를 옮 겨 다 니 는 방식 으로 이 루어 집 니 다.
public void print(){
    print(root);
}

private void print(BinaryNode<T> tree){
    if(tree == null)
        return;
    print(tree.left);
    System.out.println(tree.element + " l:" + tree.left + " r:" + tree.right);
    print(tree.right);
}

height (): 뒤쪽 으로 옮 겨 다 니 는 방식 으로 돌아 가 는 나무의 높이 를 구 합 니 다.
public int height(){
    return height(root);
}

private int height(BinaryNode<T> tree){
    if(tree == null)
        return -1;
    /*              ,     ,       */    
    else
        return 1 + Math.max(height(tree.left), height(tree.right));
}

내부 류
내부 클래스 는 이 진 트 리 의 노드 를 검색 합 니 다.노드 는 주로 데이터 와 왼쪽, 오른쪽 아이 노드 의 인용 을 유지 합 니 다.
private static class BinaryNode<T>{
    public T element;
    public BinaryNode<T> left;
    public BinaryNode<T> right;

    public BinaryNode(T ele){
        this(ele, null, null);
    }

    public BinaryNode(T ele, BinaryNode<T> l, BinaryNode<T> r){
        element = ele;
        left = l;
        right = r;
    }
}

소스 코드
import java.util.Comparator;

/** *       * @author Bingo * * @param <T>         Comparable  ,           */
public class BinarySearchTree <T>{
    /** *       */
    private BinaryNode<T> root;

    /** *   T     */
    private Comparator<T> cmp;

    /** *             */
    public BinarySearchTree(){
        this(null);
    }

    /** *          * @param cmp     */
    public BinarySearchTree(Comparator<T> cmp){
        this.cmp = null;
    }

    /** *         * @param cmp */
    public void setComparator(Comparator<T> cmp){
        this.cmp = cmp;
    }

    public boolean isEmpty(){
        return root == null;
    }

    public void clearTree(){
        root = null;
    }

    public int height(){
        return height(root);
    }

    /** *           x * @param x       * @return         true,    false */
    public boolean contains(T x){
        return contains(x, root);
    }

    /** *           * @return */
    public T findMin(){
        return findMin(root);
    }

    /** *           * @return */
    public T findMax(){
        return findMax(root);
    }

    /** *       x * @param x */
    public void insert(T x){
        root = insert(x, root);
    }

    /** *     x * @param x */
    public void remove(T x){
        root = remove(x, root);
    }

    /** *         */
    public void print(){
        print(root);
    }

    /** *            (    ) * @param x * @param tree * @return */
    private boolean contains(T x, BinaryNode<T> tree){
        if(tree == null)
            return false;
        /*     x     ,                    */
        int result = innerCompareTo(x, tree.element);
        if(result < 0)
            return contains(x, tree.left);
        else if(result > 0)
            return contains(x, tree.right);
        /* result = 0,             */
        else
            return true;
    }

    /** *               . *                              . * @param tree * @return */
    private T findMin(BinaryNode<T> tree){
        /*         */
        if(tree == null)
            return null;
        /*             ,             */
        else if(tree.left != null)
            return findMin(tree.left);
        /*        */
        else
            return tree.element;
    }

    /** *                *                              . * @param tree * @return */
    private T findMax(BinaryNode<T> tree){
        /*      */
        if(tree != null)
            /*                 , * ps:   tree       ,           . *                 ,        ! *    tree.right = tree.left                . */
            while(tree.right != null)
                tree = tree.right;
        return tree.element;
    }

    /** *         x,         ,        * @param x       * @param tree * @return */
    private BinaryNode<T> insert(T x, BinaryNode<T> tree){
        /*         ,             */
        if(tree == null)
            return new BinaryNode<T>(x);

        int result = innerCompareTo(x, tree.element);
        if(result < 0)
            tree.left = insert(x, tree.left);
        else if(result > 0)
            tree.right = insert(x, tree.right);
        else{
            //       ,        
        }
        return tree;
    }

    /** *     x    * @param x * @param tree * @return */
    private BinaryNode<T> remove(T x, BinaryNode<T> tree){
        /*             */
        if(tree == null)
            return null;

        int result = innerCompareTo(x, tree.element);
        /*           */
        if(result < 0)
            tree.left = remove(x, tree.left);
        /*           */
        else if(result > 0)
            tree.right = remove(x, tree.right);
        /* 1.         ,      ,     *                           *                   (              ,          ( 2)) */
        else if(tree.left != null && tree.right != null){
            tree.element = findMax();
        }
        /* 2.      ,                    * -              * -          ,         */
        else{
            tree = (tree.left != null) ? tree.left : tree.right; 
        }
        return tree;
    }

    /** *          ,             * @param tree */
    private void print(BinaryNode<T> tree){
        if(tree == null)
            return;
        print(tree.left);
        System.out.println(tree.element + " l:" + tree.left + " r:" + tree.right);
        print(tree.right);
    }

    /** *     ,             */
    private int height(BinaryNode<T> tree){
        if(tree == null)
            return -1;
        /*              ,     ,       */    
        else
            return 1 + Math.max(height(tree.left), height(tree.right));
    }

    /** *        * @param lhs * @param rhs * @return */
    @SuppressWarnings("unchecked")
    private int innerCompareTo(T lhs, T rhs){
        if(cmp != null)
            return cmp.compare(lhs, rhs);
        else
            return ((Comparable<T>)lhs).compareTo(rhs);
    }

    /** *    ,           * @author Bingo * * @param <T> */
    private static class BinaryNode<T>{
        public T element;
        public BinaryNode<T> left;
        public BinaryNode<T> right;

        public BinaryNode(T ele){
            this(ele, null, null);
        }

        public BinaryNode(T ele, BinaryNode<T> l, BinaryNode<T> r){
            element = ele;
            left = l;
            right = r;
        }
    }
}

좋은 웹페이지 즐겨찾기