查找算法

空间索引 - 四叉树

 ̄綄美尐妖づ 提交于 2020-03-22 11:39:10
/*--> */ /*--> */ /*--> */ /*--> */ /*--> */ /*--> */ 前言 作为程序员,应该都对二叉树都不陌生,我们都知道二叉树的变体二叉查找树,非常适合用来进行对一维数列的存储和查找,可以达到 O(logn) 的效率;我们在用二叉查找树进行插入数据时,根据一个数据的值和树结点值的对比,选择二叉树的两个叉之一向下,直到叶子结点,查找时使用二分法也可以迅速找到需要的数据。 但二叉树只支持一维数据,如一个标量数值,对地图上的位置点这种有xy两个方向上的信息却无能为力,那么是否有一种树能够支持二维数据的快速查询呢? 四叉树 介绍 四元树又称四叉树是一种树状数据结构,在每一个节点上会有四个子区块。四元树常应用于二维空间数据的分析与分类。它将数据区分成为四个象限。 今天要介绍的四叉树可以认为是二叉查找树的高维变体,它适合对有二维属性的数据进行存储和查询,当然四叉树存储的也不一定是二维数据,而是有着二维属性的数据,如有着 x,y 信息的点,用它还可以用来存储线和面数据。它有四个 叉 ,在数据插入时,我们通过其二维属性(一般是 x,y)选择四个叉之一继续向下,直至叶子结点,同样使用“四分法”来迅速查找数据。四叉树的一般图形结构如下: 聪明的小伙伴一定想到了适合存储和查询三维数据的八叉树,它们原理是一致的,不过我们暂不讨论。 分类 四叉树常见的应用有图像处理

C#实现平衡多路查找树(B树)

有些话、适合烂在心里 提交于 2020-03-22 05:59:22
写在前面:搞了SQL Server时间也不短了,对B树的概念也算是比较了解。去网上搜也搜不到用C#或java实现的B树,干脆自己写一个。实现B树的过程中也对很多细节有了更深的了解。 简介 B树是一种为辅助存储设计的一种数据结构,在1970年由R.Bayer和E.mccreight提出。在文件系统和数据库中为了减少IO操作大量被应用。遗憾的是,他们并没有说明为什么取名为B树,但按照B树的性质来说B通常被解释为Balance。在国内通常有说是B-树,其实并不存在B-树,只是由英文B-Tree直译成了B-树。 一个典型的 B树如图1所示。 图1.一个典型的B树 符合如下特征的树才可以称为B树: 根节点如果不是叶节点,则至少需要两颗子树 每个节点中有N个元素,和N+1个指针。每个节点中的元素不得小于最大节点容量的1/2 所有的叶子位于同一层级(这也是为什么叫平衡树) 父节点元素向左的指针必须小于节点元素,向右的指针必须大于节点元素,比如图1中Q的左指针必须小于Q,右指针必须大于Q 为什么要使用B树 在计算机系统中,存储设备一般分为两种,一种为主存(比如说CPU二级缓存,内存等),主存一般由硅制成,速度非常快,但每一个字节的成本往往高于辅助存储设备很多。还有一类是辅助存储(比如硬盘,磁盘等),这种设备通常容量会很大,成本也会低很多,但是存取速度非常的慢,下面我们来看一下最常见的辅存--硬盘。

数据结构——树的相关概念

强颜欢笑 提交于 2020-03-21 12:58:05
平衡二叉树和二叉查找树 至多有两个子节点的树成为二叉树 1)平衡二叉树 1)树的左右高度差不能超过1. 2)任何往下递归的左子树和右子树,必须符合第一条性质 3)没有任何节点的空树或只有跟节点的树也是平衡二叉树 树的节点Node是key value的形式。因为key可能不连续,甚至不是整数,所以我们没办法使用数组来表示,这个时候我们就可以用二叉查找树来实现 2)二叉查找树 树如其名,二叉查找树非常擅长数据查找。 二叉查找树额外增加了如下要求:它的左子树上所有节点的值都小于它,而它的右子树上所有节点的值都大于它。 查找的过程从树的根节点开始,沿着简单的判断向下走,小于节点值的往左边走,大于节点值的往右边走,直到找到目标数据或者到达叶子节点还未找到。 通常设计Node节点来表示key value这样的数据对 二叉查找树的insert package bobo.algo; // 二分搜索树 // 由于Key需要能够进行比较,所以需要extends Comparable<Key> public class BST<Key extends Comparable<Key>, Value> { // 树中的节点为私有的类, 外界不需要了解二分搜索树节点的具体实现 private class Node { private Key key; private Value value; private

Python常见的几种算法

人盡茶涼 提交于 2020-03-21 10:48:59
冒泡排序 冒泡排序 (英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 冒泡排序算法的运作如下: 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 针对所有的元素重复以上的步骤,除了最后一个。 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 冒泡排序的分析 交换过程图示(第一次): 那么我们需要进行n-1次冒泡过程,每次对应的比较次数如下图所示: def bubble_sort(alist): for j in range(len(alist)-1,0,-1): # j表示每次遍历需要比较的次数,是逐渐减小的 for i in range(j): if alist[i] > alist[i+1]: alist[i], alist[i+1] = alist[i+1], alist[i] li = [54,26,93,17,77,31,44,55,20] bubble_sort(li) print(li) 时间复杂度

B+树索引

ぃ、小莉子 提交于 2020-03-19 00:18:19
结构上 B树中关键字集合分布在整棵树中,叶节点中不包含任何关键字信息,而B+树关键字集合分布在叶子结点中,非叶节点只是叶子结点中关键字的索引; B树中任何一个关键字只出现在一个结点中,而B+树中的关键字必须出现在叶节点中,也可能在非叶结点中重复出现; 性能上(也即为什么说B+树比B树更适合实际应用中 操作系统 的文件索引和 数据库 索引?) 不同于B树只适合随机检索,B+树同时支持随机检索和顺序检索; B+树的磁盘读写代价更低。B+树的内部结点并没有指向关键字具体信息的指针,其内部结点比B树小,盘块能容纳的结点中关键字数量更多,一次性读入内存中可以查找的关键字也就越多,相对的,IO读写次数也就降低了。而IO读写次数是影响索引检索效率的最大因素。 B+树的查询效率更加稳定。B树搜索有可能会在非叶子结点结束,越靠近根节点的记录查找时间越短,只要找到关键字即可确定记录的存在,其性能等价于在关键字全集内做一次二分查找。而在B+树中,顺序检索比较明显,随机检索时,任何关键字的查找都必须走一条从根节点到叶节点的路,所有关键字的查找路径长度相同,导致每一个关键字的查询效率相当。 (数据库索引采用B+树的主要原因是,)B-树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。B+树的叶子节点使用指针顺序连接在一起,只要遍历叶子节点就可以实现整棵树的遍历

集合框架系列 Map(十):HashMap

柔情痞子 提交于 2020-03-18 18:17:13
目录 1 概述 2 原理 3 源码分析  3.1 构造方法   3.1.1 构造方法分析   3.1.2 初始容量、负载因子、阈值  3.2 查找  3.3 遍历  3.4 插入   3.4.1 插入逻辑分析   3.4.2 扩容机制   3.4.3 链表树化、红黑树链化与拆分  3.5 删除  3.6 其他细节  3.7 总结 1. 概述 本篇文章我们来聊聊大家日常开发中常用的一个集合类 - HashMap 。HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现。HashMap 允许 null 键和 null 值,在计算哈键的哈希值时,null 键哈希值为 0。HashMap 并不保证键值对的顺序,这意味着在进行某些操作后,键值对的顺序可能会发生变化。另外,需要注意的是,HashMap 是非线程安全类,在多线程环境下可能会存在问题。 在本篇文章中,我将会对 HashMap 中常用方法、重要属性及相关方法进行分析。需要说明的是,HashMap 源码中可分析的点很多,本文很难一一覆盖,请见谅。 2. 原理 上一节说到 HashMap 底层是基于散列算法实现,散列算法分为散列再探测和拉链式。HashMap 则使用了拉链式的散列算法,并在 JDK 1.8 中引入了红黑树优化过长的链表。数据结构示意图如下: 对于拉链式的散列算法,其数据结构是由数组和链表(或树形结构)组成

sqlite索引的原理

喜你入骨 提交于 2020-03-18 13:59:12
引言 这篇文章 ,里面讲到对于一个41G大小、包含百万条记录的数据库进行查询操作,如果利用了索引,可以把操作耗时从37s降到0.2s。 那么什么是索引呢?利用索引可以加快数据库查询操作的原理是什么呢? 索引的基本原理 数据库提供了一种持久化的数据存储方式,从数据库中查询数据库是一个基本的操作,查询操作的效率是很重要的。 对于查询操作来说,如果被查询的数据已某种方式组织起来,那么查询操作的效率会极大提高。 在数据库中,一条记录会有很多列。如果把这些记录按照列Col1以某种数据结构组织起来,那么列Col2一定是乱序的。 因此,数据库在原始数据之外,维护了满足特定查找算法的数据结构,指向原始数据,称之为 索引 。 举例来说,在下面的图中,数据库有两列Col1、Col2。在存储时,按照列Col1组织各行,比如Col1已二叉树方式组织。如果查找col1中的某一个值,利用二叉树进行二分查找,不需要遍历整个数据库。 这样一来列Col2就是乱序的。为了解决这个问题,为Col2建立了索引,即把Col2也按照某种数据结构(这里是二叉树)组织起来。这样子查找列Col2时只需要进行二分查找即可。  索引的实现 由于数据库是存储在磁盘上的,因此实现索引用的数据结构会存储在磁盘上。磁盘的IO是需要注意的问题。 二叉树 二叉树是一种经典的数据结构,但是并不适合进行数据库索引。

平方根计算

我的未来我决定 提交于 2020-03-17 11:06:28
二分法 描述:假设数据是按升序排序的,对于给定值x,从序列的中间位置开始比较,如果当前位置值等于x,则查找成功;若x小于当前位置值,则在数列的前半段中查找;若x大于当前位置值则在数列的后半段中继续查找,直到找到为止。 简单介绍:在有序的有N个元素的数组中查找用户输进去的数据x。 算法如下: 确定查找范围front=0,end=N-1,计算中项mid(front+end)/2。若a[mid]=x或front>=end,则结束查找;否则,向下继续。若a[mid]<x,说明待查找的元素值只可能在比中项元素大的范围内,则把mid+1的值赋给front,并重新计算中项mid,继续执行步骤2;若a[mid]>x,说明待查找的元素值只可能在比中项元素小的范围内,则把mid-1的值赋给end,并重新计算mid,继续执行步骤2。 以求解2的平方根的程序为基础,编程实现:输入一个浮点数,计算其平方根。要求如下: 不准使用如sqrt()的库函数代码必须上传并确保自己测试通过输入一个浮点数输出该浮点数的平方根 提示: 测试输出与标准测试结果不符的一种可能原因是计算精度不够,简单的解决方法是将循环计算的次数提高,如将20次提高到30次。 一定要考虑到根大于0的情况,而不是求根号2那样利用1.0这个下限。 测试说明测试输入:2 预期输出:1.41421 # include <iostream> using

算法实践:查找最接近的元素(最近不能相等)

左心房为你撑大大i 提交于 2020-03-17 03:23:23
查找最接近的元素(最近不能相等) 描述 查找最接近的元素 输入 第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。 第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000之间。 第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。 接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000之间。 (注意:最接近但是不能相等。输入保证有解) 输出 m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。 若有多个值满足条件,输出最小的一个。 样例 3 2 5 8 2 10 5 8 2 难度 高 解法 要求找到与target最接近,但是不能相等的数,意味着要严格思考检查目标的左右边界最接近的值的位置。 lowerBound函数:在包含n个元素的、从小到大排序的int数组nums里查找比给定整数target小的,下标最大的元素。找到则返回其下标,找不到则返回-1------二分查找 upperBound函数:在包含n个元素的、从小到大排序的int数组nums里查找比给定整数target大的,下标最小的元素。找到则返回其下标,找不到则返回-1------二分查找 先判断target如果比第一个小,比最后一个大的情况,然后是分别有左右边界的情况,接着返回有左右边界中最接近的那个数

SKYPE原理分析

天涯浪子 提交于 2020-03-15 15:56:33
无论传统电信运营商愿意看到与否,以Skype为代表的VoIP软件已经在全球拥有越来越多的拥趸。Skype的工作原理究竟是什么?为什么会掀起如此巨大的波澜?从技术角度看它究竟有哪些优势?电信运营商在VoIP领域下一步该如何发展? Skype与 P2P 所谓P2P(Peer to Peer),其最本质的含义即“对等”,该技术最早是用于网络中对等节点之间的资源和信息共享的技术,通常人们所知道的是将P2P技术用在文件下载过程 中,即网络上的对等终端在下载共享文件的同时又作为一个“种子”为其他对等终端提供资源和信息。后来,Skype在网络通话业务系统中灵活应用了该技术。 由于冲击了传统通信领域,Skype在引起很多争议的同时也使人耳目一新,可以说,Skype是发展和演进了的P2P应用。目前对于P2P技术还没有规范 的定义,结合其已有的应用,就更广泛的意义而言, P2P技术是指网络中的所有节点都动态参与到路由、信息处理和带宽增强等工作中,而不是单纯依靠服务器来完成这些工作。 Skype是P2P技术演进到混合模式后的典型应用,它结合了集中式和分布式的特点,在网络的边缘节点采用集中式的网络结构,而在超级节点之间采用分布式的网络结构,混合模式的P2P网络模型如图1所示。 从网络模型来看,这种混合模式的P2P是经过多年的发展和演进而来的,严格讲,这已经不是纯粹的对等网络结构了,只能称做发展了的P2P