Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

지극히 개인적인 개발블로그

트리 본문

CS/자료구조

트리

코드분쇄기 2019. 9. 11. 20:43

트리는 데이터 사이의 계층 관계를 나타내는 자료구조입니다.

 

 

노드가 왼쪽 자식과 오른쪽 자식을 갖는 트리를 이진트리라고 합니다. 이때 각 노드의 자식은 2명 이하만 유지해야 합니다.

 

루트부터 노드가 채워져 있으면서 같은 레벨에서는 왼쪽에서 오른쪽으로 노드가 채워져 있는 이진트리를 완전 이진트리라고 합니다. 위 예시또한 완전 이진트리라고 할 수 있습니다.

 

import java.util.Comparator;

public class BinTree<K, V> {
    //노드
    static class Node<K, V>{
        private K key;              //키 값
        private V data;             //데이터
        private Node<K, V> left;    //왼쪽 자식 노드
        private Node<K, V> right;   //오른쪽 자식 노드

        //생성자
        Node(K key, V data, Node<K, V> left, Node<K, V>right){
            this.key = key;
            this.data = data;
            this.left = left;
            this.right = right;
        }

        //키 값을 반환
        K getKey(){
            return key;
        }

        // 데이터를 반환
        V getData(){
            return data;
        }

        //데이터를 출력
        void print(){
            System.out.println(data);
        }
    }

    private Node<K, V> root;                                 //루트: 루트에 대한 참조를 보존,유지하는 필드
    private Comparator<? super K> comparator = null;        //비교자: 키 값의 대소 관계를 비교하는 비교자

    //생성자
    public BinTree(){
        root = null;
    }

    //생성자
    public BinTree(Comparator<? super K> c){
        this();
        comparator = c;
    }

    //두 키 값을 비교
    private int comp(K key1, K key2){
        return (comparator == null) ? ((Comparable<K>key1).compareTo(key2))
                                        :comparator.compare(key1, key2);
    }

    //키에 의한 검색
    public V search(K key){
        Node<K, V> p =root;

        while(true){
            if(p == null)
                return null;
            int cond = comp(key, p.getKey());
            if(cond == 0)
                return p.getValue();
            else if(cond < 0)
                p = p.left;
            else
                p = p.right;
        }
    }

    //node를 루트로 하는 서브 트리에 노드<K, V>를 삽입
    private void addNode(Node<K, V> node, K key, V data){
        int cond = comp(key, node.getKey());
        if(cond == 0)
            return;
        else if(cond < 0){
            if(node.left == null)
                node.left = new Node<K, V>(key, data, null, null);
            else
                addNode(node.left, key, data);
        }else{
            if(node.right == null)
                node.right = new Node<K, V>(key, data, null, null);
            else
                addNode(node.right, key, data);
        }
    }

    //노드를 삽입
    public void add(K key, V data){
        if(root == null)
            root = new Node<K, V>(key, data, null, null);
        else
            addNode(root, key, data);
    }

    //키 값이 key인 노드를 삭제
    public boolean remove(K key){
        Node<K, V> p = root;
        Node<K, V> parent = null;
        boolean isLeftChild = true;

        while(true){
            if(p == null)
                return false;
            int cond = comp(key, p.getKey());
            if(cond == 0)
                break;
            else{
                parent = p;
                if(cond < 0) {
                    isLeftChild = true;
                    p = p.left;
                } else{
                    isLeftChild = false;
                    p = p.right;
                }
            }
        }

        if(p.left == null){
            if(p == root)
                root = p.right;
            else if(isLeftChild)
                parent.left = p.right;
            else
                parent.right = p.right;
        }else if(p.right == null){
            if(p == root)
                root = p.left;
            else if(isLeftChild)
                parent.left = p.left;
            else
                parent.right = p.left;
        }else{
            parent = p;
            Node<K, V> left = p.left;
            isLeftChild = true;
            while(left.right != null){
                parent = left;
                left = left.right;
                isLeftChild = false;
            }
            p.key = left.key;
            p.data = left.data;
            if(isLeftChild)
                parent.left = left.left;
            else
                parent.right = left.left;
        }
        return true;
    }

    //node를 루트로 하는 서브 트리의 노드를 키 값의 오름차순으로 출력
    private void printSubTree(Node node){
        if(node != null){
            printSubTree(node.left);
            System.out.println(node.key + " "+node.data);
            printSubTree(node.right);
        }
    }

    //모든 노드를 키 값의 오름차순으로 출력
    public void print(){
        printSubTree(root);
    }
}