数据结构与算法:二分查找

罕见数据结构

  • 简朴数据结构(必需明白和控制)

    • 有序数据结构:栈、行列、链表。有序数据结构省空间(贮存空间小)
    • 无序数据结构:鸠合、字典、散列表,无序数据结构省时刻(读取时刻快)
  • 庞杂数据结构

    • 树、 堆

本系列主要内容

  • 数组和列表: 最经常运用的数据结构

    • 与链表比拟,数组具有更好的缓存位置。
  • 栈和行列: 与列表相似然则更庞杂数据结构
  • 链表: 怎样经由历程它们战胜数组的不足,

    • 链表许可在迭代时期有效地从序列中的任何位置插进去或删除元素。
    • 链表的一个瑕玷是接见时刻是线性的(而且难以管道化)。(更快的接见,如随机接见,是不可行的)
  • 字典: 将数据以键-值对的的情势贮存
  • 散列(表): 适用于疾速查找和检索
  • 鸠合: 适用于存储只涌现一次的元素
  • 二叉树: 以层级的情势存储数据
  • 图和图算法: 收集建模的抱负挑选
  • 算法:包括排序、搜刮、图形算法
  • 高等算法: 动态计划、贪婪算法、BF、分治、回溯等算法范式
  • 加密算法:

有序数据结构

数组

列表

行列

链表

无序列数据结构

鸠合

字典

散列(表)

简朴算法 => 二分查找

《数据结构与算法:二分查找》

二分查找是搜刮算法中的一种,用来搜刮有序数组

二分查找:是一种简朴算法,其输入是一个有序的元素列表(必需有序的缘由稍后诠释)。假如要
查找的元素包括在列表中,二分查找返回其位置;不然返回null

《数据结构与算法:二分查找》

Javascript ES6完成

非递归的

/** 
 * 函数binarySearch接收一个有序数组和一个元素。 假如指定的元素包括在数组中, 这个
 函数将返回其位置。 你将跟踪要在个中查找的数组部份—— 开始时为全部数组。
*/
const binarySearch = (list, item) => {
  // 数组要查找的局限
  // low、high用于跟踪要在个中查找的列表部份
  let low = 0  
  let high = list.length - 1

  while(low <= high) { // 只需局限没有缩小到只包括一个元素
    const mid = Math.floor((low + high) / 2)
    const guess = list[mid] // 找到中心的元素

    if(guess === item) { // 找到元素
      return mid
    }
    if(guess > item) { // 猜想的数大了
      high = mid - 1
    } else { // 猜想的数小了
      low = mid + 1
    }
  }

  return null
}

const myList = [1, 3, 5, 7, 9]

console.log(binarySearch(myList, 3))
console.log(binarySearch(myList, -1))

递归的


 
const binarySearch = (list, item, low, hight) => {
  let arrLength = list.length
  while (low <= high) {
    let mid = Math.floor((low + high) / 2)
    let guess = list[mid]

    if( guess === item ) {
      return mid
    } else if (guess > item) {
      high = mid - 1
      list = list.slice(0, mid)
      return binarySearch(list, item, low, high)
    } else {
      low = mid + 1
      list = list.slice(low, arrLength)
      return binarySearch(list, item, low, high)
    }
  }
  return null 
}

const createArr = (n) => Array.from({length: n}, (v, k) => k + 1)

const myList = createArr(100)
let low = 0
let high = myList.length - 1

console.log(binarySearch(myList, 3, low, high))
console.log(binarySearch(myList, -1, low, high))

找一个均衡二叉树末了一个节点

Python完成

运转时刻(时刻庞杂度)

《数据结构与算法:二分查找》

二分查找的运转时刻为对数时刻(或log时刻)。
假如列表包括100个元素,最多要猜7次;假如列表包括40亿个数字,最多
需猜32次。
《数据结构与算法:二分查找》
即: 2的7次方 = 100

《数据结构与算法:二分查找》
简朴查找时刻是 y= ax 的线性方方程
所以很轻易得出结论

跟着元素数目的增添(x增添),二分查找须要的时刻(y)并不多, 而简朴查找须要的时刻(y)却许多。

因而,跟着列表的增进,二分查找的速率比简朴查找快得多。

为搜检长度为n的列表,二分查找须要实行log n次操纵。运用大O示意法,
这个运转时刻怎样示意呢?O(log n)。一般而言,简朴算法的大O示意法像下面如许
《数据结构与算法:二分查找》

《数据结构与算法:二分查找》

大O标记

大O标记中指定的算法的增进递次

《数据结构与算法:二分查找》

以下是一些最经常运用的 大O标记法 列表以及它们与差别大小输入数据的机能比较。

《数据结构与算法:二分查找》

  • O(log n),也叫对数时刻,如许的算法包括二分查找
  • O(n),也叫线性时刻,如许的算法包括简朴查找。
  • O(n * log n),如许的算法包括疾速排序——一种速率较快的排序算法。
  • 《数据结构与算法:二分查找》,如许的算法包括挑选排序——一种速率较慢的排序算法
  • O(n!),如许的算法包括接下来将引见的旅行商题目的解决方案——一种异常慢的算法

《数据结构与算法:二分查找》

小结

  • 算法的速率指的并不是时刻,而是操纵数的增速。
  • 议论算法的速率时,我们说的是跟着输入的增添,其运转时刻将以什么样的速率增添。
  • 算法的运转时刻用大O示意法示意。
  • O(log n)比O(n)快,当须要搜刮的元素越多时,前者比后者快得越多

疾速排序

快排和二分查找都基于一种叫做「分治」的算法头脑,经由历程对数据举行分类处置惩罚,不停下降数目级,完成O(logN)(对数级别,比O(n) 这类线性庞杂度更低的一种,快排中心是二分法的O(logN) ,现实庞杂度为O(N*logN) )的庞杂度。

快排也许的流程是:

  1. 随机挑选数组中的一个数 A,以这个数为基准
  2. 其他数字跟这个数举行比较,比这个数小的放在其左侧,大的放到其右侧
  3. 经由一次轮回以后,A 左侧为小于 A 的,右侧为大于 A 的
  4. 这时刻将左侧和右侧的数再递归上面的历程

《数据结构与算法:二分查找》

旅行商题目–庞杂度O(n!)的算法

简朴的讲假如旅行者要去5个都市,先后递次肯定有5*4*3*2*1 = 120种排序。(这类排序想一想高中时刻学到过的排序学问)

推而广之,触及n个都市时,须要实行n!(n的阶乘)次操纵才计算出效果。因而运转时刻

为O(n!),即阶乘时刻。除非触及的都市数很少,不然须要实行异常多的操纵。假如触及的都市

数凌驾100,基础就不能在合理的时刻内计算出效果——等你计算出效果,太阳都没了。

这类算法很蹩脚!,可别无挑选。这是计算机科学范畴待解的题目之一。关于这个题目,现在还没有找到更快的算法,有些很智慧的人以为这个题目基础就没有更奇妙的算法。
面临这个题目,我们能做的只是去找出近似答案。

末了须要指出的一点是,高水平的读者可研究一下二叉树

关于二叉树,戳这里: 数据结构与算法:二叉树算法

罕见演习

在一个二维数组中,每一行都根据从左到右递增的递次排序,每一列都根据从上到下递增的递次排序。请完成一个函数,输入如许的一个二维数组和一个整数,推断数组中是不是含有该整数。

参考

算法图解
JavaScript 算法与数据结构
https://github.com/egonSchiel…
【算法】时刻庞杂度
【算法】空间庞杂度
InterviewMap 时刻庞杂度
https://github.com/trekhleb/j…
每周一练 之 数据结构与算法(Stack)
All Algorithms implemented in Python

    原文作者:AlexZ33
    原文地址: https://segmentfault.com/a/1190000018342920
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞