6-5、6、7... 二分搜索树的查询操作、前序遍历

  • 二分搜索树的contains方法实现逻辑如下:
 1 // 看二分搜索树中是否包含元素e
 2     public boolean contains(E e){
 3         return contains(root, e);
 4     }
 5
 6     // 看以node为根的二分搜索树中是否包含元素e, 递归算法
 7     private boolean contains(Node node, E e){
 8
 9         if(node == null)
10             return false;
11
12         if(e.compareTo(node.e) == 0)
13             return true;
14         else if(e.compareTo(node.e) < 0)
15             return contains(node.left, e);
16         else // e.compareTo(node.e) > 0
17             return contains(node.right, e);
18     }
  • 6-6 二分搜索树的前序遍历

二分搜索树的遍历操作,遍历操作就是把所有节点都访问一遍

前序遍历:先访问节点,在访问左右子树。

递归代码:先写递归终止条件,再写递归组成逻辑

 1 // 二分搜索树的前序遍历
 2     public void preOrder(){
 3         preOrder(root);
 4     }
 5
 6     // 前序遍历以node为根的二分搜索树, 递归算法
 7     private void preOrder(Node node){
 8         if(node == null)    //递归终止条件
 9             return;
10
11         System.out.println(node.e);
12         preOrder(node.left);   //递归组成逻辑
13         preOrder(node.right);
14     }

6-7 二分搜索树的中序遍历和后序遍历

  • 中序遍历的业务逻辑如下:
 1 // 二分搜索树的中序遍历
 2 public void inOrder() {
 3     inOrder(root);
 4 }
 5
 6 // 中序遍历以node为根的二分搜索树,递归算法
 7 private void inOrder(Node node) {
 8
 9     if (node == null) {
10         return;
11     }
12
13     inOrder(node.left);
14     System.out.print(node.e);
15     inOrder(node.right);
16
17 }

  • 后序遍历的业务逻辑如下:
 1 // 二分搜索树的后序遍历
 2 public void postOrder() {
 3     postOrder(root);
 4 }
 5
 6 // 后序遍历以node为根的二分搜索树,递归算法
 7 private void postOrder(Node node) {
 8
 9     if (node == null) {
10         return;
11     }
12     postOrder(node.left);
13     postOrder(node.right);
14     System.out.print(node.e);
15
16 }

6-9 二分搜索树前序遍历的非递归实现

  • 前序遍历是最自然的遍历方式,也是最常用的遍历方式;中序遍历的结果是按从小到大的顺序的排列的;后序遍历可以用于为二分搜索树释放内存。
  • 利用"栈"实现二分搜索树的非递归前序遍历

//结合视频、PDF看这段代码

 1  // 二分搜索树的非递归前序遍历
 2     public void preOrderNR(){
 3
 4         Stack<Node> stack = new Stack<>();//stack使用泛型型,里面装的是Node类对象
 5         stack.push(root);   //入栈,向根节点中添加root
 6         while(!stack.isEmpty()){
 7             Node cur = stack.pop();  //把栈顶元素来出来,放进cur中,cur节点就是我们当前要访问的节点
 8             System.out.println(cur.e);
 9
10             if(cur.right != null)  //前序遍历顺序:根→left节点→right节点,由于栈是后入先出的,所以right节点先入栈,left节点后入栈
11                 stack.push(cur.right);
12             if(cur.left != null)
13                 stack.push(cur.left);
14         }
15     }
  • 6-10 二分搜索树的层序遍历
  • 二分搜索树的前序、中序、后序遍历本质上都是深度优先的遍历
  • 二分搜索树的"层序遍历"属于"广度优先"算法。
  • 利用"队列"实现二分搜索树的"层序遍历"
 1   // 二分搜索树的层序遍历
 2     public void levelOrder(){
 3
 4         Queue<Node> q = new LinkedList<>();//对于层序遍历来说,需要使用一个队列,这里使用Java自带的Queue(导入包Queue),不过Java的Queue本质是一个接口,真正实现它是时候需要实现一个具体的底层数据结构,选择使用链表的方式来实现(导入包LinkedList)。
 5         q.add(root);
 6         while(!q.isEmpty()){
 7             Node cur = q.remove();//队列中的元素出队之后的那个元素就是我们当前要访问的元素
 8             System.out.println(cur.e);
 9
10             if(cur.left != null)
11                 q.add(cur.left);
12             if(cur.right != null)
13                 q.add(cur.right);
14         }
15     }

对应图,一定是从根节点开始不停的向左走、向右走,走不动了,就找到最小、最大值。

  • 寻找二分搜索树的最大值、最小值
 1  // 寻找二分搜索树的最小元素
 2     public E minimum(){
 3         if(size == 0)
 4             throw new IllegalArgumentException("BST is empty");
 5
 6         Node minNode = minimum(root);  //maximum(root):以root为根的二分搜索树的最小值
 7         return minNode.e;//返回以root为根的二分搜索树的最小元素值
 8     }
 9
10     // 返回以node为根的二分搜索树的最小值所在的节点
11     private Node minimum(Node node){
12         if( node.left == null )//向左走走不动了
13             return node;
14
15         return minimum(node.left);//如果不满足if条件,执行这一步
16     }
17
18     // 寻找二分搜索树的最大元素
19     public E maximum(){
20         if(size == 0)
21             throw new IllegalArgumentException("BST is empty");
22
23         return maximum(root).e;
24     }
25
26     // 返回以node为根的二分搜索树的最大值所在的节点
27     private Node maximum(Node node){
28         if( node.right == null )
29             return node;
30
31         return maximum(node.right);
32     }
  • 删除二分搜索树的最大值、最小值

变成变成

 1   // 从二分搜索树中删除最小值所在节点, 返回最小值
 2     public E removeMin(){
 3         E ret = minimum();
 4         root = removeMin(root);//从root开始尝试删除最小值所在节点
 5         return ret;
 6     }
 7
 8     // 删除掉以node为根的二分搜索树中的最小节点
 9     // 返回删除节点后新的二分搜索树的根
10     private Node removeMin(Node node){
11
12         if(node.left == null){  //不能向左走了,当前节点node就是最小值所在节点,要删到这个节点
13             Node rightNode = node.right;//要删的这个当前节点可能是有右子树的,右子树不能丢。 创建rightNode,保存当前节点的右子树
14             node.right = null;//对将要删除的节点让它的right等于空,也就是将要删除的node节点从二叉树中脱离。
15             size --;//删除掉了一个元素,整体size要--
16             return rightNode;//返回rightNode,起到删除最小值所在节点的作用。把node删除,当前二分搜索树的根就是node的右孩子:node.right( rightNode )
17         }
18
19         node.left = removeMin(node.left);//如果没有递归到底,不满足if条件,说明node还有左孩子,要做的是:去删除掉到node左子树对应的最小值
20         return node;//删除掉到node左子树对应的最小值后,对于当前以node为根的二分搜索树,它的根节点依然是node,将它返回
21     }
22
23     // 从二分搜索树中删除最大值所在节点
24     public E removeMax(){
25         E ret = maximum();
26         root = removeMax(root);
27         return ret;
28     }
29
30     // 删除掉以node为根的二分搜索树中的最大节点
31     // 返回删除节点后新的二分搜索树的根
32     private Node removeMax(Node node){
33
34         if(node.right == null){
35             Node leftNode = node.left;
36             node.left = null;
37             size --;
38             return leftNode;
39         }
40
41         node.right = removeMax(node.right);
42         return node;
43     }

看下面这个图便于理解

6-12 删除二分搜索树的任意元素

具体实现代码:

  • 删除二分搜索树中指定元素所对应的节点
 1   // 从二分搜索树中删除元素为e的节点
 2     public void remove(E e){
 3         root = remove(root, e);
 4     }
 5
 6     // 删除掉以node为根的二分搜索树中值为e的节点, 递归算法
 7     // 返回删除节点后新的二分搜索树的根
 8     Node remove(Node node, E e){
 9
10         if( node == null )
11             return null;
12
13         if( e.compareTo(node.e) < 0 ){
14             node.left = remove(node.left , e);  //到node的左子树中尝试删除e
15             return node;
16         }
17         else if(e.compareTo(node.e) > 0 ){
18             node.right = remove(node.right, e);
19             return node;
20         }
21         else{   // e.compareTo(node.e) == 0代删除的e和当前节点的e相等
22
23             // 待删除节点左子树为空的情况
24             if(node.left == null){
25                 Node rightNode = node.right;
26                 node.right = null;
27                 size --;
28                 return rightNode;
29             }
30
31             // 待删除节点右子树为空的情况
32             if(node.right == null){
33                 Node leftNode = node.left;
34                 node.left = null;
35                 size --;
36                 return leftNode;
37             }
38
39             // 待删除节点左右子树均不为空的情况
40
41             // 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
42             // 用这个节点顶替待删除节点的位置
43             Node successor = minimum(node.right);
44             size ++;
45
46             successor.right = removeMin(node.right);
47             successor.left = node.left;
48
49             node.left = node.right = null;
50             size --;
51
52             return successor;
53         }

原文地址:https://www.cnblogs.com/make-big-money/p/10333564.html

时间: 2024-11-07 16:29:37

6-5、6、7... 二分搜索树的查询操作、前序遍历的相关文章

二分搜索树的深度优先遍历和广度优先遍历

二分搜索树的特点 二分搜索树首先是一个二叉树,其次其必须满足的条件是:每个节点的键值必须大于其左子节点,每个节点的键值必须小于其右子节点,这样以左右孩子为根的子树仍为二分搜索树,需要注意的是,二分搜索树不一定是一颗完全二叉树. 深度优先遍历 深度优先遍历的基本思想:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次.深度优先遍历的非递归的通用做法是采用栈.要特别注意的是,二分搜索树的深度优先遍历比较特殊,可以细分为前序遍历.中序遍历.后序遍历. 前序遍历:先访问当前节点,再依次

第二十六篇 玩转数据结构——二分搜索树

1.. 二叉树 跟链表一样,二叉树也是一种动态数据结构,即,不需要在创建时指定大小. 跟链表不同的是,二叉树中的每个节点,除了要存放元素e,它还有两个指向其它节点的引用,分别用Node left和Node right来表示. 类似的,如果每个节点中有3个指向其它节点的引用,就称其为"三叉树"... 二叉树具有唯一的根节点. 二叉树中每个节点最多指向其它的两个节点,我们称这两个节点为"左孩子"和"右孩子",即每个节点最多有两个孩子. 一个孩子都没有

实现二分搜索树

二分搜索树具有以下特点: 1 二分搜索树是一颗二叉树 2 二分搜索树每个节点的左子树的值都小于该节点的值,每个节点右子树的值都大于该节点的值 3 任意一个节点的每棵子树都满足二分搜索树的定义 基于第二点我们的需要插入树的元素实现Comparable接口,下面实现二分搜索树的原型,这个类具有二分搜索树的基本成员变量和方法,之后再实现对元素的操作方法. public class BST<E extends Comparable<E>> { private class Node{ pub

并行二分搜索树bianry search tree

二分搜索树是一种设计良好的有序集合,在平衡的情况下,查找search,插入insertion,删除deletion都具有O(logn)的计算时间.本文讨论实现二分搜索树的具体细节. 二分搜索树的每个结点包含key域,以及至多两个孩子结点,并且左孩子小于当前结点的值,右孩子大于当前结点值.为了方便操作,每个结点还需要维护父结点的信息.从上面的描述可以看出,二分搜索树的任何一个子树同样也是二分搜索树. 搜索操作是所有操作的基础.搜索操作可以很容易用递归过程描述:key>cur.key,则搜索右子树:

二分搜索树(Binary Search Tree)

目录 什么是二叉树? 什么是二分搜索树? 二分搜索树的基本操作 二分搜索树添加新元素 二分搜索树的遍历(包含非递归实现) 删除二分搜索树中的元素 什么是二叉树? ??在实现二分搜索树之前,我们先思考一下,为什么要有树这种数据结构呢?我们通过企业的组织机构.文件存储.数据库索引等这些常见的应用会发现,将数据使用树结构存储后,会出奇的高效,树结构本身是一种天然的组织结构.常见的树结构有:二分搜索树.平衡二叉树(常见的平衡二叉树有AVL和红黑树).堆.并查集.线段树.Trie等.Trie又叫字典树或前

《算法导论》动态规划—最优二分搜索树

案例 ?假如我们现在在设计一个英文翻译程序,要把英文翻译成汉语,显然我们需要知道每个单词对应的汉语意思.我们可以建立一颗二分搜索树来实现英语到汉语的关联.为了更快速地翻译,我们可以使用AVL树或者红黑树使每次查询的时间复杂度Θ(lgn),实际上对于字典翻译程序来说这么做存在一个问题,比如"the"这个单词经常用,却很有可能存在于十分远离树根的位置,而"machicolation"这种不常用的单词很可能存在于十分靠近树根的位置,这就导致查询频率高的单词需要的查询时间更

十八 二分搜索树的三种遍历方式

三种遍历方式: package com.lt.datastructure.BST; public class BST<E extends Comparable<E>> { private class Node{ public E e; Node left,right; public Node(E e) { this.e = e; this.left = left; this.right = right; } } private Node root; private int size

十九 二分搜索树的广度优先遍历

二分搜索树广度优先遍历的实现: /* * 二分搜索树的层序遍历(广度优先遍历),队列实现 * 广度优先遍历优势在于更快找到想要查询的元素,主要用于搜索策略,算法设计--最短路径(无权图) */ public void levelOrder(){ Queue<Node> q = new LinkedList<>(); q.add(root); while(!q.isEmpty()){ Node cur = q.remove(); System.out.println(cur.e);

漫谈二叉搜索树的基本算法(三种思路实现查询操作)

  前面我们说了二叉树前序中序后序遍历的递归非递归算法的实现,下面我们再来说说二叉搜索树~   二叉排序树分为静态查找(find)和动态查找(insert.delete) 二叉搜索树:一棵二叉树,可以为空:如果不为空,满足下列性质: 1.非空左子树的所有键值小于其根结点的键值. 2.非空右子树的所有键值大于其根结点的键值 3.左右子树都是二叉搜索树!! 2.以上是二叉搜索树(也叫二叉排序树)的一些基本操作,此处我们先说一下二叉树的结点定义·· 代码中判断当前结点位置情况的辅助方法以及简单的 ge