栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【数据结构与算法】② 二叉搜索树

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【数据结构与算法】② 二叉搜索树

目录
  • 一、二叉搜索树
  • 二、BST 接口设计
  • 三、实现(add)
    • 添加节点步骤(☆☆☆☆☆)
    • 添加进 BST 里面的元素必须具有可比较性
      • (1) BST 限制泛型必须具有可比较性
      • (2) 传比较器给 BST
      • (3) 结合 (1) 和 (2)
  • 四、二叉树网址和打印器的使用

一、二叉搜索树

  • 任意一个节点的值都大于其左子树所有节点的值
  • 任意一个节点的值都小于其右子树所有节点的值
  • BST 存储的元素必须具备可比较性(如 int、double 等)
  • BST 存储自定义类型,需要指定比较方式
  • BST 存储的元素不能为 null

左边的都比我小,右边的都比我大。

二、BST 接口设计
public class BinarySearchTree {

    public int size() {
        return 0;
    }

    public boolean isEmpty() {
        return true;
    }

    public void clear() {

    }

    public void add(E element) {

    }

    public void remove(E element) {

    }

    public boolean contains(E element) {
        return true;
    }

}
  • BST 的元素没有索引的概念
三、实现(add)

  • 二叉搜索树(BinarySearchTree)中会维护一个节点类
  • BST 内部会维护根节点
public class BinarySearchTree {  

    
    private static class Node {
        // 节点上存储的元素
        E element;
        // 左子节点
        Node left;
        // 右子节点
        Node right;
        // 父节点
        Node parent;

        
        public Node(E element, Node parent) {
            this.element = element;
            this.parent = parent;
        }
    }

}
  • 元素非空检测
    
    private void elementNotNullCheck(E element) {
        if (element == null)
            throw new IllegalArgumentException("Element must not be null!");
    }
添加节点步骤(☆☆☆☆☆)
  • 找到父节点(parent)
  • 创建新节点(node)
  • parent.left = node 或 parent.right = node
  • 遇到值相等?新值覆盖旧值
添加进 BST 里面的元素必须具有可比较性 (1) BST 限制泛型必须具有可比较性

BinarySearchTree 限制,能够放进 BinarySearchTree 泛型的元素必须实现 Comparable 接口。Comparable 接口中要求实现它的类必须实现 compareTo 方法,进而提供比较逻辑。

public class BinarySearchTree> {
    // 记录二叉搜索树的元素个数
    private int size;
    private Node root; // 根节点

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void clear() {

    }

    public void add(E element) {
        elementNotNullCheck(element);

        // BST 中存储的第一个节点(根节点)
        if (size == 0 && root == null) {
            root = new Node<>(element, null);
            size++;
            return;
        }

        // 假设 node 是父节点
        Node node = root;
        Node parent = root;
        int cmp = 0;

        while (node != null) {
            cmp = compare(element, node.element);
            parent = node;
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) {
                node = node.left;
            } else {
                return;
            }
        }

        // 创建新节点
        Node newNode = new Node<>(element, parent);

        if (cmp > 0) {
            parent.right = newNode;
        } else if (cmp < 0) {
            parent.left = newNode;
        }
        size++;

    }

    public void remove(E element) {

    }

    public boolean contains(E element) {
        return true;
    }

    
    private int compare(E e1, E e2) {
        return e1.compareTo(e2);
    }

    
    private void elementNotNullCheck(E element) {
        if (element == null)
            throw new IllegalArgumentException("Element must not be null.");
    }

    
    private static class Node {
        E element;
        Node left;
        Node right;
        Node parent;

        public Node(E element, Node parent) {
            this.element = element;
            this.parent = parent;
        }
    }

}
public interface Comparable {

    int compareTo(E e);

}
public class Student implements Comparable {
    private int score;

    public int getScore() {
        return score;
    }

    public Student(int score) {
        this.score = score;
    }

    @Override
    public int compareTo(Student student) {
        return score - student.getScore();
    }
}
public class Main {

    public static void main(String[] args) {

        BinarySearchTree bst = new BinarySearchTree<>();
        bst.add(new Student(100));
        bst.add(new Student(66));
        bst.add(new Student(78));

    }

}

Student 类的比较逻辑写死了

(2) 传比较器给 BST
public class BinarySearchTree {
    // 记录二叉搜索树的元素个数
    private int size;
    private Node root; // 根节点

    private Comparator comparator;

    public BinarySearchTree(Comparator comparator) {
        this.comparator = comparator;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void clear() {

    }

    public void add(E element) {
        elementNotNullCheck(element);

        // BST 中存储的第一个节点(根节点)
        if (size == 0 && root == null) {
            root = new Node<>(element, null);
            size++;
            return;
        }

        // 假设 node 是父节点
        Node node = root;
        Node parent = root;
        int cmp = 0;

        while (node != null) {
            cmp = compare(element, node.element);
            parent = node;
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) {
                node = node.left;
            } else {
                return;
            }
        }

        // 创建新节点
        Node newNode = new Node<>(element, parent);

        if (cmp > 0) {
            parent.right = newNode;
        } else if (cmp < 0) {
            parent.left = newNode;
        }
        size++;

    }

    public void remove(E element) {

    }

    public boolean contains(E element) {
        return true;
    }

    
    private int compare(E e1, E e2) {
        return comparator.compare(e1, e2);
    }

    
    private void elementNotNullCheck(E element) {
        if (element == null)
            throw new IllegalArgumentException("Element must not be null.");
    }

    
    private static class Node {
        E element;
        Node left;
        Node right;
        Node parent;

        public Node(E element, Node parent) {
            this.element = element;
            this.parent = parent;
        }
    }

}
public interface Comparator {

    int compare(E e1, E e2);

}
public class Student {
    private int score;

    public int getScore() {
        return score;
    }

    public Student(int score) {
        this.score = score;
    }

}
public class Main2 {

    private static class StudentComparator1 implements Comparator {
        @Override
        public int compare(Student e1, Student e2) {
            return e1.getScore() - e2.getScore();
        }
    }

    private static class StudentComparator2 implements Comparator {
        @Override
        public int compare(Student e1, Student e2) {
            return e2.getScore() - e1.getScore();
        }
    }

    public static void main(String[] args) {
        BinarySearchTree bst1 = new BinarySearchTree<>(new StudentComparator1());
        BinarySearchTree bst2 = new BinarySearchTree<>(new StudentComparator2());

    }

}

强制限制 BST 必须提供比较器了

(3) 结合 (1) 和 (2)
public class BinarySearchTree3 {
    // 记录二叉搜索树的元素个数
    private int size;
    private Node root; // 根节点

    private Comparator comparator;

    public BinarySearchTree3(Comparator comparator) {
        this.comparator = comparator;
    }

    public BinarySearchTree3() {
        this.comparator = null;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public void clear() {

    }

    public void add(E element) {
        elementNotNullCheck(element);

        // BST 中存储的第一个节点(根节点)
        if (size == 0 && root == null) {
            root = new Node<>(element, null);
            size++;
            return;
        }

        // 假设 node 是父节点
        Node node = root;
        Node parent = root;
        int cmp = 0;

        while (node != null) {
            cmp = compare(element, node.element);
            parent = node;
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) {
                node = node.left;
            } else {
                return;
            }
        }

        // 创建新节点
        Node newNode = new Node<>(element, parent);

        if (cmp > 0) {
            parent.right = newNode;
        } else if (cmp < 0) {
            parent.left = newNode;
        }
        size++;

    }

    public void remove(E element) {

    }

    public boolean contains(E element) {
        return true;
    }

    
    private int compare(E e1, E e2) {
        if (comparator != null) return comparator.compare(e1, e2);
        return ((Comparable)e1).compareTo(e2);
    }

    
    private void elementNotNullCheck(E element) {
        if (element == null)
            throw new IllegalArgumentException("Element must not be null.");
    }

    
    private static class Node {
        E element;
        Node left;
        Node right;
        Node parent;

        public Node(E element, Node parent) {
            this.element = element;
            this.parent = parent;
        }
    }

} 
public interface Comparable {

    int compareTo(E e);

}
public interface Comparator {

    int compare(E e1, E e2);

}
public class Student {
    private int score;

    public int getScore() {
        return score;
    }

    public Student(int score) {
        this.score = score;
    }

}
public class Main3 {

    private static class StudentComparator1 implements Comparator {
        @Override
        public int compare(Student e1, Student e2) {
            return e1.getScore() - e2.getScore();
        }
    }

    private static class StudentComparator2 implements Comparator {
        @Override
        public int compare(Student e1, Student e2) {
            return e2.getScore() - e1.getScore();
        }
    }

    public static void main(String[] args) {
        BinarySearchTree3 bst1 = new BinarySearchTree3<>(new StudentComparator1());
        BinarySearchTree3 bst2 = new BinarySearchTree3<>(new StudentComparator2());
        BinarySearchTree3 bst3 = new BinarySearchTree3<>();

    }

}
Comparable 和 Comparator 在 jdk 的 util 包中都有的

匿名内部类和 Lambda 表达式:

public class Main4 {

    
    private static class StudentComparator1 implements Comparator {
        @Override
        public int compare(Student e1, Student e2) {
            return e1.getScore() - e2.getScore();
        }
    }

    
    private static class StudentComparator2 implements Comparator {
        @Override
        public int compare(Student e1, Student e2) {
            return e2.getScore() - e1.getScore();
        }
    }

    public static void main(String[] args) {
        BinarySearchTree4 bst1 = new BinarySearchTree4<>(new StudentComparator1());
        BinarySearchTree4 bst2 = new BinarySearchTree4<>(new StudentComparator2());
        BinarySearchTree4 bst3 = new BinarySearchTree4<>();

        // 匿名内部类
        BinarySearchTree4 bst4 = new BinarySearchTree4<>(new Comparator() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore() - o2.getScore();
            }
        });

        // Lambda 表达式
        BinarySearchTree4 bst5 = new BinarySearchTree4<>((o1, o2) -> o2.getScore() - o1.getScore());
    }

}
四、二叉树网址和打印器的使用

https://520it.com/binarytrees/
① BinarySearchTree 实现 BinaryTreeInfo 接口
② 实现四个方法

    @Override
    public Object root() {
        return root;
    }

    @Override
    public Object left(Object node) {
        return ((Node) node).left;
    }

    @Override
    public Object right(Object node) {
        return ((Node) node).right;
    }

    @Override
    public Object string(Object node) {
        return ((Node) node).element;
    }

③ BinaryTrees.pringln(bst) 打印

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1019678.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号