简单记录 - bobo老师的玩转算法系列–玩转算法 - 二分搜索树

二叉搜索树 Binary Search Tree

查找问题 Searching Problem

查找问题是计算机中非常重要的基础问题

二分查找法 Binary Search

v

<v v >v

对于有序数列,才能使用二分查找法 (排序的作用)

二分查找法的思想在1946年提出。

第一个没有bug的二分查找法在1962年才出现。

操作:实现二分查找法

非递归的二分查找算法 BinarySearch.java

package algo;

// 非递归的二分查找算法
public class BinarySearch { // 我们的算法类不允许产生任何实例
private BinarySearch() {} // 二分查找法,在有序数组arr中,查找target
// 如果找到target,返回相应的索引index
// 如果没有找到target,返回-1
public static int find(Comparable[] arr, Comparable target) { // 在arr[l...r]之中查找target
int l = 0, r = arr.length-1;
while( l <= r ){ //int mid = (l + r)/2;
// 防止极端情况下的整形溢出,使用下面的逻辑求出mid
int mid = l + (r-l)/2; if( arr[mid].compareTo(target) == 0 )
return mid; if( arr[mid].compareTo(target) > 0 )
r = mid - 1;
else
l = mid + 1;
} return -1;
} // 测试非递归的二分查找算法
public static void main(String[] args) { int N = 1000000;
Integer[] arr = new Integer[N];
for(int i = 0 ; i < N ; i ++)
arr[i] = new Integer(i); // 对于我们的待查找数组[0...N)
// 对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身
// 对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1
for(int i = 0 ; i < 2*N ; i ++) {
int v = BinarySearch.find(arr, new Integer(i));
if (i < N)
assert v == i;
else
assert v == -1;
} return;
}
}

使用递归地方式实现二分查找法

递归实现通常思维起来更容易。

递归在性能上会略差。

练习:实现二分查找法的递归实现

package algo;

// 递归的二分查找算法
public class BinarySearch2 { // 我们的算法类不允许产生任何实例
private BinarySearch2() {} private static int find(Comparable[] arr, int l, int r, Comparable target){ if( l > r )
return -1; //int mid = (l+r)/2;
// 防止极端情况下的整形溢出,使用下面的逻辑求出mid
int mid = l + (r-l)/2; if( arr[mid].compareTo(target) == 0 )
return mid;
else if( arr[mid].compareTo(target) > 0 )
return find(arr, l, mid-1, target);
else
return find(arr, mid+1, r, target);
} // 二分查找法,在有序数组arr中,查找target
// 如果找到target,返回相应的索引index
// 如果没有找到target,返回-1
public static int find(Comparable[] arr, Comparable target) { return find(arr, 0, arr.length-1, target);
} // 测试递归的二分查找算法
public static void main(String[] args) { int N = 1000000;
Integer[] arr = new Integer[N];
for(int i = 0 ; i < N ; i ++)
arr[i] = new Integer(i); // 对于我们的待查找数组[0...N)
// 对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身
// 对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1
for(int i = 0 ; i < 2*N ; i ++) {
int v = BinarySearch2.find(arr, new Integer(i));
if (i < N)
assert v == i;
else
assert v == -1;
} return;
}
}

比较

Main

package algo;

import algo.BinarySearch;
import algo.BinarySearch2; // 比较非递归和递归写法的二分查找的效率
// 非递归算法在性能上有微弱优势
public class Main { private Main(){} public static void main(String[] args) { int N = 1000000;
Integer[] arr = new Integer[N];
for(int i = 0 ; i < N ; i ++)
arr[i] = new Integer(i); // 测试非递归二分查找法
long startTime = System.currentTimeMillis(); // 对于我们的待查找数组[0...N)
// 对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身
// 对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1
for(int i = 0 ; i < 2*N ; i ++) {
int v = BinarySearch.find(arr, new Integer(i));
if (i < N)
assert v == i;
else
assert v == -1;
}
long endTime = System.currentTimeMillis(); System.out.println("Binary Search (Without Recursion): " + (endTime - startTime) + "ms"); // 测试递归的二分查找法
startTime = System.currentTimeMillis(); // 对于我们的待查找数组[0...N)
// 对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身
// 对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1
for(int i = 0 ; i < 2*N ; i ++) {
int v = BinarySearch2.find(arr, new Integer(i));
if (i < N)
assert v == i;
else
assert v == -1;
}
endTime = System.currentTimeMillis();
System.out.println("Binary Search (With Recursion): " + (endTime - startTime) + "ms"); }
}
D:\Environments\jdk-11.0.2\bin\java.exe -javaagent:D:\Java\ideaIU-2019.2.win\lib\idea_rt.jar=9455:D:\Java\ideaIU-2019.2.win\bin -Dfile.encoding=UTF-8 -classpath D:\IdeaProjects\imooc\Learning-Algorithms\05-Binary-Search-Tree\out\production\01-Binary-Search algo.Main
Binary Search (Without Recursion): 337ms
Binary Search (With Recursion): 514ms Process finished with exit code 0

比较非递归和递归写法的二分查找的效率

非递归算法在性能上有微弱优势

【二分搜索树】1、二分查找法的实现 - Binary Search的更多相关文章

  1. [Swift]LeetCode272. 最近的二分搜索树的值 II $ Closest Binary Search Tree Value II

    Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...

  2. 二分查找(Binary Search)

    二分查找(Binary Search): int BinarySearch(int *array, int N, int key) { ; int left, right, mid; left = ; ...

  3. Leetcode之二分法专题-704. 二分查找(Binary Search)

    Leetcode之二分法专题-704. 二分查找(Binary Search) 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 t ...

  4. 二分查找(Binary Search)的递归和非递归

    Binary Search 有时候我们也把它叫做二进制查找 是一种较为高效的再数组中查找目标元素的方法 我们可以通过递归和非递归两种方式来实现它 //非递归 public static int bin ...

  5. LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14

    108. 将有序数组转换为二叉搜索树 108. Convert Sorted Array to Binary Search Tree 题目描述 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索 ...

  6. 二分查找(Binary Search)的基本实现

    关于二分查找法二分查找法主要是解决在"一堆数中找出指定的数"这类问题. 而想要应用二分查找法,这"一堆数"必须有一下特征: 1,存储在数组中2,有序排列 所以如 ...

  7. 二分查找(binary search)java实现及时间复杂度

    概述 在一个已排序的数组seq中,使用二分查找v,假如这个数组的范围是[low...high],我们要的v就在这个范围里.查找的方法是拿low到high的正中间的值,我们假设是m,来跟v相比,如果m& ...

  8. [Swift]LeetCode108. 将有序数组转换为二叉搜索树 | Convert Sorted Array to Binary Search Tree

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. Fo ...

  9. [Swift]LeetCode109. 有序链表转换二叉搜索树 | Convert Sorted List to Binary Search Tree

    Given a singly linked list where elements are sorted in ascending order, convert it to a height bala ...

随机推荐

  1. .net5+nacos+ocelot 配置中心和服务发现实现

    最近一段时间 因公司业务需要,需要使用.net5做一套微服务的接口,使用nacos 做注册中心和配置中心,ocelot做网关. 因为ocelot 支持的是consol和eureka,如果使用nacos ...

  2. 图的遍历DFS

    图的遍历DFS 与树的深度优先遍历之间的联系 树的深度优先遍历分为:先根,后根 //树的先根遍历 void PreOrder(TreeNode *R){ if(R!=NULL){ visit(R); ...

  3. 一、安装LoadRunner12

    今天接到任务最近要进行性能测试(刚开始搞自动化,有要搞性能测试,领导嫌我不忙吧),之前做接口测试用过Jmeter,也可以使用Jmeter做性能测试,但公司要求用LoadRunner,开始学习性能测试和 ...

  4. 接口测试工具 Jmeter使用笔记(一:编写一个http请求)

    记录学习过程 一.安装Jmeter 1.JAVA环境 JDK下载地址http://java.sun.com/javase/downloads/index.jsp 配置系统变量: (1)JAVA_HOM ...

  5. Python开发:一个直播弹幕机器人诞生过程,自动发送弹幕

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. Python爬取B站弹幕视频讲解 https://www.bilibili.com/vide ...

  6. [日常摸鱼]bzoj2875[NOI2012]随机数生成器-矩阵快速幂

    好裸的矩阵快速幂-然而我一开始居然构造不出矩阵- 平常两个的情况都是拿相邻两项放在矩阵里拿去递推的-然后我就一直构造不出来-其实把矩阵下面弄成1就好了啊orz #include<cstdio&g ...

  7. MySQL数据归档小工具推荐--mysql_archiver

    一.主要概述 MySQL数据库归档历史数据主要可以分为三种方式:一.创建编写SP.设置Event:二.通过dump导入导出:三.通过pt-archiver工具进行归档.第一种方式往往受限于同实例要求, ...

  8. 太酷炫了!!我会Python 导包八种方法,你呢?

    1. 直接 import 人尽皆知的方法,直接导入即可 >>> import os >>> os.getcwd() '/home/wangbm'复制代码 与此类似的 ...

  9. EF Core 封装方法Expression<Func<TObject, bool>>与Func<TObject, bool>区别

    unc<TObject, bool>是委托(delegate) Expression<Func<TObject, bool>>是表达式 Expression编译后就 ...

  10. H3C路由器配置——动态路由RIP协议

    一.静态路由的不足 静态路由适用于:小规模的网络.架构不怎么调整的网络.没有环路的网络 二.RIP协议工作过程 2.1.工作特点 n路由信息协议RIP(Routing Information Prot ...