Java实现二叉查找树

二叉查找(搜索)树

二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小,右节点的值要比父节点的值大。

在理想的情况下,二叉查找树增删查改的时间复杂度为O(logN)(其中N为节点数),最坏的情况(线性)下为O(N)。它的高度决定了它的查找效率,当它的高度为logN+1时,我们就说二叉查找树是平衡的。  


上代码,难理解的地方有注释微笑

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * @ClassName Binaryintree类
 * @Author whw
 * @Date 2017年8月25日 上午10:52:35
 * @Version 1.0
 * @Description 二叉查找树
 */
public class BinaryTree<T extends Comparable<T>> {
    private Node<T> rootNode;
    private ArrayList<T> dateList;

    /**
     * @ClassName Node类
     * @Description 内部类 结点
     * @param  
     */
    static class Node<T> {
        T date;
        Node<T> leftNode;
        Node<T> rightNode;

        public Node() {
        }

        public Node(T date) {
            this.date = date;
        }

        @Override
        public String toString() {
            return date + " ";
        }
    }
    
    public BinaryTree() {
    }

    public BinaryTree(T[] array) {
        for (int i = 0; i < array.length; i++) {
            insert(array[i]);
        }
    }
    
    public BinaryTree(ArrayList<T> dateList) {
        for (int i = 0; i < dateList.size(); i++) {
            insert(dateList.get(i));	//随机访问
        }
    }

    // 插入
    public void insert(T date) {
        Node<T> newNode = new Node<T>(date);
        if (rootNode == null) {
            rootNode = newNode;
        } else {
            Node<T> currentNode = rootNode;
            while (true) {
                if (date.compareTo(currentNode.date) == 0)
                    return;
                if (date.compareTo(currentNode.date) < 0) {
                    Node<T> tempNode = currentNode.leftNode;
                    if (tempNode == null) {
                        currentNode.leftNode = newNode;
                        return;
                    }
                    currentNode = currentNode.leftNode;
                } else {
                    Node<T> tempNode = currentNode.rightNode;
                    if (tempNode == null) {
                        currentNode.rightNode = newNode;
                        return;
                    }
                    currentNode = currentNode.rightNode;
                }
            }
        }
    }
    
    // 查询与数据相同的节点并返回
    private Node<T> findNode(T date) {
        Node<T> currentNode = rootNode;
        while (currentNode != null) {
            if (date == currentNode.date)
                return currentNode;
            if (date.compareTo(currentNode.date) < 0) {
                currentNode = currentNode.leftNode;
            } else {
                currentNode = currentNode.rightNode;
            }
        }
        return null;
    }

    // 数据节点是否存在
    public boolean isExist(T date) {
        return findNode(date) == null ? false : true;
    }

    // 先序遍历递归实现
    private void preOrder(Node<T> node, List<T> dateList) {
        if (node != null) {
            dateList.add(node.date);
            preOrder(node.leftNode, dateList);
            preOrder(node.rightNode, dateList);
        }
    }
    public List<T> preOrder() {
        dateList = new ArrayList<>();
        if (rootNode == null) {
            return dateList;
        }
        preOrder(rootNode, dateList);
        return dateList;
    }

    // 先序遍历非递归实现
    public List<T> preOrderOfStack() {
        dateList = new ArrayList<T>();
        if (rootNode == null) {
            return dateList;
        }
        Stack<Node<T>> nodeStack = new Stack<Node<T>>();
        nodeStack.push(rootNode);
        while (!nodeStack.empty()) {
            Node<T> topNode = nodeStack.pop();
            dateList.add(topNode.date);
            if (topNode.rightNode != null) {
                nodeStack.push(topNode.rightNode);
            }
            if (topNode.leftNode != null) {
                nodeStack.push(topNode.leftNode);
            }
        }
        return dateList;
    }

    // 中序遍历递归实现
    private void inOrder(Node<T> node, List<T> dateList) {
        if (node != null) {
            inOrder(node.leftNode, dateList);
            dateList.add(node.date);
            inOrder(node.rightNode, dateList);
        }
    }
    public List<T> inOrder() {
        dateList = new ArrayList<>();
        if (rootNode == null) {
            return dateList;
        }
        inOrder(rootNode, dateList);
        return dateList;
    }

    // 中序遍历非递归实现
    public List<T> inOrderOfStack() {
        dateList = new ArrayList<T>();
        if (rootNode == null) {
            return dateList;
        }
        Stack<Node<T>> nodeStack = new Stack<Node<T>>();
        Node<T> currentNode = rootNode;
        while (currentNode != null || !nodeStack.empty()) {
            while (currentNode != null) {
                nodeStack.push(currentNode);
                currentNode = currentNode.leftNode;
            }
            currentNode = nodeStack.pop();
            dateList.add(currentNode.date);
            currentNode = currentNode.rightNode;
        }
        return dateList;
    }

    // 后序遍历递归实现
    private void postOrder(Node<T> node, ArrayList<T> dateList) {
        if (node != null) {
            postOrder(node.leftNode, dateList);
            postOrder(node.rightNode, dateList);
            dateList.add(node.date);
        }
    }
    public List<T> postOrder() {
        dateList = new ArrayList<>();
        if (rootNode == null) {
            return dateList;
        }
        postOrder(rootNode, dateList);
        return dateList;
    }

    // 后序遍历非递归实现
    public List<T> postOrderOfStack() {
        dateList = new ArrayList<T>();
        if (rootNode == null) {
            return dateList;
        }
        Stack<Node<T>> nodeStack = new Stack<Node<T>>();
        Node<T> currentNode = rootNode;
        Node<T> lastUseRightNode = null; //记录最后访问的右节点,防止再次访问
        while (currentNode != null || !nodeStack.empty()) {
            while (currentNode != null) {
                nodeStack.push(currentNode);
                currentNode = currentNode.leftNode; //先访问左节点
            }
            currentNode = nodeStack.peek().rightNode; //再访问右节点
            if (currentNode == null || currentNode == lastUseRightNode) { //防止死循环
                currentNode = nodeStack.pop();
                dateList.add(currentNode.date);
                lastUseRightNode = currentNode;
                currentNode = null;
            }
        }
        return dateList;
    }
}



欢迎批评指正!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉查找树(Binary Search Tree)是一种常见的数据结构,它的每个节点最多有两个子节点,左子节点的值小于父节点的值,右子节点的值大于父节点的值。Java 实现二叉查找树的代码如下: ``` public class BinarySearchTree { private Node root; private class Node { private int key; private Node left; private Node right; public Node(int key) { this.key = key; } } public void insert(int key) { root = insert(root, key); } private Node insert(Node x, int key) { if (x == null) { return new Node(key); } if (key < x.key) { x.left = insert(x.left, key); } else if (key > x.key) { x.right = insert(x.right, key); } return x; } public boolean contains(int key) { return contains(root, key); } private boolean contains(Node x, int key) { if (x == null) { return false; } if (key == x.key) { return true; } else if (key < x.key) { return contains(x.left, key); } else { return contains(x.right, key); } } public void delete(int key) { root = delete(root, key); } private Node delete(Node x, int key) { if (x == null) { return null; } if (key < x.key) { x.left = delete(x.left, key); } else if (key > x.key) { x.right = delete(x.right, key); } else { if (x.left == null) { return x.right; } else if (x.right == null) { return x.left; } else { Node t = x; x = min(t.right); x.right = deleteMin(t.right); x.left = t.left; } } return x; } private Node min(Node x) { if (x.left == null) { return x; } else { return min(x.left); } } private Node deleteMin(Node x) { if (x.left == null) { return x.right; } x.left = deleteMin(x.left); return x; } } ``` 这段代码实现二叉查找树的插入、查找和删除操作。其中,插入操作使用递归实现,查找和删除操作也是递归实现的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值