数据结构二分搜索树详解

Posted 牧小农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构二分搜索树详解相关的知识,希望对你有一定的参考价值。

一、树结构

树是一种很特别的数据结构,树这种数据结构叫做 “树” 就是因为它 长得像一棵树 。但是这棵树画成的图长得却是一棵倒着的树,根在上,叶在下。树是图的一种,树和图的区别就在于:树是没有环的,而图是可以有环的。

树状图是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

二、为什么要有树结构

2.1 树结构是一种天然的组织结构

比如说电脑中的文件夹,我们需要找到一个特定的文件,需要到某个文件夹下去找这个文件,计算机的文件存储的结构来源于生活。再比如说图书馆,我们知道图书馆里面有 历史类、数理类、计算机类,我们想要找到关于java的书籍,就需要到计算机类的Java中去找到我们需要的图书【数据结构】二分搜索树详解比如公司里面的层级结构:CEOHR CTO等等,还有我们比较常见的家谱等等,都是类似于树结构

【数据结构】二分搜索树详解

  • 将数据使用树结构后,会更加的高效

三、二分搜索树

3.1 特点

  • 二分搜索树是一个动态数据结构

  • 二分搜索树也是一颗二叉树(也叫多叉树)

  • 二分搜索树的每个节点的值都大于其左子树的所有节点的值,同时每个节点的值都小于其右子树的所有节点的值

  • 存储的元素必须有可比较性, Java中的话就要求二分搜索树保存的数据类型要实现Comparable接口, 或者使用额外的比较器实现

  • 每一颗子树也是二分搜索树

  • 二分搜索树具有唯一根节点,同时在二叉树中最底下是它的叶子节点 

  • 【数据结构】二分搜索树详解

  •  二分搜索树具有唯根节点,每个节点最多有两个孩子(左边的叫左孩子,右边的叫右孩子),同时每个节点最多有一个父亲

二分搜索树天然的具有递归特性

  • 每个节点的左子树也是二叉树

  • 每个节点的右子树也是二叉树 【数据结构】二分搜索树详解


二叉树不一定是满的,一个接电脑也是二叉树、空也是二叉树

【数据结构】二分搜索树详解

四、具体代码实现

在进行相关操作之前, 先定义一个支持泛型的节点类, 用于存储二分搜索树每个节点的信息, 这个类作为二分搜索树的一个内部类, 二分搜索树的类声明以及Node节点类声明如下:

 
   
   
 
  1. public class BST<E extends Comparable<E>> {


  2. private class Node{

  3. public E e;

  4. public Node left,right;


  5. public Node(E e){

  6. this.e = e;

  7. left = null;

  8. right = null;

  9. }

  10. }

  11. //节点

  12. private Node root;

  13. // 树容量

  14. private int size;


  15. public BST(){

  16. root = null;

  17. size = 0;


  18. }


  19. public int size(){

  20. return size;

  21. }


  22. public boolean isEmpty(){

  23. return size == 0;

  24. }


  25. }

4.1 添加元素

二分搜索树添加元素的非递归写法,和链表很像,由于二分搜索树本身的递归特性, 所以可以很方便的使用递归实现向二分搜索树中添加元素,【数据结构】二分搜索树详解代码实现:

 
   
   
 
  1. //向二分搜索树添加新的元素e

  2. public void add(E e){

  3. root = add(root,e);

  4. }


  5. //向以Node为根的二分搜索树中插入元素 E,递归算法

  6. //返回插入新节点后二分搜索树的根

  7. private Node add(Node node,E e){


  8. if(node == null){

  9. size++;

  10. return new Node(e);

  11. }

  12. if(e.compareTo(node.e) < 0)

  13. node.left = add(node.left,e);

  14. else if(e.compareTo(node.e) > 0)

  15. node.right = add(node.right,e);


  16. return node;

  17. }

4.2 查找元素

由于二分搜索树没有下标, 所以针对二分搜索树的查找操作, 我们需要定义一个 contains() 方法, 查看二分搜索树是否包含某个元素, 返回一个布尔型变量

代码实现:

 
   
   
 
  1. //看二分是搜索树中是否包含元素e

  2. public boolean contains(E e){

  3. return contains(root,e);

  4. }


  5. //看以Node为根的二分搜索树中是否包含元素e,递归算法

  6. private boolean contains(Node node,E e){


  7. if(node == null)

  8. return false;


  9. if(e.compareTo(node.e) == 0)

  10. return true;

  11. else if(e.compareTo(node.e) < 0)

  12. return contains(node.left,e);

  13. else //e.compareTo(node.e) > 0

  14. return contains(node.right,e);

  15. }

4.3 遍历操作

一、 什么是遍历操作

  • 遍历操作就是把所有的节点都访问一遍

  • 访问的原因和业务相关

  • 遍历分类

前序遍历 : 对当前节点的遍历在对左右孩子节点的遍历之前, 遍历顺序 : 当前节点->左孩子->右孩子 中序遍历 : 对当前节点的遍历在对左右孩子节点的遍历中间, 遍历顺序 : 左孩子->当前节点->右孩子 后序遍历 : 对当前节点的遍历在对左右孩子节点的遍历之后, 遍历顺序 : 左孩子->右孩子->当前节点二、 前序遍历

 
   
   
 
  1. //二分搜索树前序遍历

  2. public void preOrder(){

  3. preOrder(root);

  4. }


  5. //前序遍历以Node为根的二分搜索树,递归算法

  6. private void preOrder(Node node){


  7. if(node == null)

  8. return;


  9. System.out.println(node.e);

  10. preOrder(node.left);

  11. preOrder(node.right);

  12. }


  13. public void preOrderNR(){

  14. Stack<Node> stack = new Stack<>();

  15. stack.push(root);

  16. while(!stack.isEmpty()){

  17. Node cur = stack.pop();

  18. System.out.println(cur.e);


  19. if(cur.right != null)

  20. stack.push(cur.right);


  21. if(cur.left != null)

  22. stack.push(cur.left);

  23. }

  24. }


三、 中序遍历【数据结构】二分搜索树详解

 
   
   
 
  1. //二分搜索树的中序遍历

  2. public void inOrder(){

  3. inOrder(root);

  4. }


  5. //中序遍历以Node为根的二分搜索树,递归算法

  6. private void inOrder(Node node){

  7. if(node ==null)

  8. return;

  9. inOrder(node.left);

  10. System.out.println(node.e);

  11. inOrder(node.right);

  12. }


四、 后序遍历【数据结构】二分搜索树详解

 
   
   
 
  1. //二分搜索树的后序遍历

  2. public void postOrder(){

  3. inOrder(root);

  4. }


  5. public void levelOrder(){

  6. Queue<Node> q = new LinkedList<Node>();

  7. q.add(root);


  8. while (!q.isEmpty()){

  9. Node cur = q.remove();

  10. System.out.println(cur.e);


  11. if(cur.left != null)

  12. q.add(cur.left);

  13. if(cur.right != null)

  14. q.add(cur.right);


  15. }

  16. }



  17. //后序遍历以Node为根的二分搜索树,递归算法

  18. private void postOrder(Node node){

  19. if(node ==null)

  20. return;

  21. inOrder(node.left);

  22. inOrder(node.right);

  23. System.out.println(node.e);

  24. }


五、 理解前中后【数据结构】二分搜索树详解二分搜索树前序非递归写法



以上是关于数据结构二分搜索树详解的主要内容,如果未能解决你的问题,请参考以下文章

Java数据结构二叉搜索树增插,删,创详解

二分搜索树(Binary Search Tree)

敲黑板!数据结构精讲之二分搜索树

学习数据结构笔记(11) --- [二分搜索树(BinarySearchtTree)]

数据结构之二分搜索树

二分搜索树