diff --git a/README.md b/README.md index 08a3314..b7e94c7 100644 --- a/README.md +++ b/README.md @@ -113,12 +113,16 @@ ## 海量数据处理 -* 分而治之/Hash映射 + hash统计/trie树/红黑树/二叉搜索树 + 堆排序/快速排序/归并排序 +* Hash映射/分而治之 +* Bitmap +* Bloom filter(布隆过滤器) +* Trie树 +* 数据库索引 +* 倒排索引(Inverted Index) * 双层桶划分 -* Bloom filter 、Bitmap -* Trie树/数据库/倒排索引 * 外排序 -* 分布处理之 Hadoop/Mapreduce +* simhash算法 +* 分布处理之Mapreduce ## 算法设计思想 @@ -140,13 +144,14 @@ 《剑指offer》 《编程之美》 《结构之法:面试和算法心得》 +《算法谜题》 都是思维题 ### 基础 《编程珠玑》Programming Pearls 《编程珠玑(续)》 《数据结构与算法分析》 -《Algorithms》 这本近千页的书只有6章,其中四章分别是排序,查找,图,字符串,足见简介细致 +《Algorithms》 这本近千页的书只有6章,其中四章分别是排序,查找,图,字符串,足见介绍细致 ### 算法设计 diff --git a/pre.md b/pre.md deleted file mode 100644 index 6c2b6e2..0000000 --- a/pre.md +++ /dev/null @@ -1,70 +0,0 @@ - - -### 数学是基础 - -* 微积分 -* 概率论和统计学 -* 线性代数(矩阵,向量) -* 数值数学(数值分析,线性规划,凸优化理论,常见数值优化算法) -* 实分析和泛函的基础 - - - -### 机器学习 - -从大量数据中找到规律和知识,然后用规律和知识做决策 -机器学习偏向数学问题推导,数据挖掘就是抽特征 -不要沉迷于数学公式推导,理解如何运用数据 - - -分类器 - -* Naive Bayes -* Linear Discriminant Analysis -* Logistic Regression -* Linear SVM -* Kernel SVM -* Adaboost -* Decision -* Neural network - - -非监督模型 -* 数据处理与可视化:PCA,LDA,MDS -* 聚类算法 -* 稀疏编码 - - -基本不会去实现这些基础算法,都有现成的开源工具 - -* 概率图模型(Probabilistic graphical model) -* 两个核心的机器学习模型:Latent Dirichlet Allocation(LDA) Probabilistic Matrix Factorization(PMF) -* 统计计算(Statistical computing) -* 深度学习(Deep learning) -* 优化(optimization) -* PAC学习理论(PAC Learning) -* 非参数贝叶斯统计(Non-parametric Bayesian statistics) - -参考链接:http://www.zhihu.com/question/21714701 - - - -分类 -聚类 -模式识别 - -SVM -贝叶斯 - - - -学好python -http://julyedu.com/course/getDetail?course_id=34#discard julyedu 课程大纲 - - -### 数据挖掘 - -`数据挖掘`是指从大量的数据中自动搜索隐藏于其中的有着特殊关系性的信息和知识的过程。(from 知乎的描述) - - - diff --git a/数据库中的算法/README.md b/数据库中的算法/README.md index d657601..e2a4cfb 100644 --- a/数据库中的算法/README.md +++ b/数据库中的算法/README.md @@ -27,6 +27,7 @@ 基于排序 + 基于散列 @@ -34,6 +35,7 @@ ### 连接树 动态规划 + 贪婪算法 @@ -61,7 +63,7 @@ ## 参考 -《数据库系统实现》 +《数据库系统实现》 《redis设计与实现》 diff --git a/海量数据处理/README.md b/海量数据处理/README.md index 5bbe6c0..0b6f35e 100644 --- a/海量数据处理/README.md +++ b/海量数据处理/README.md @@ -7,6 +7,18 @@ 针对空间,就一个办法,大而化小,分而治之。常采用hash映射 +* Hash映射/分而治之 +* Bitmap +* Bloom filter(布隆过滤器) +* Trie树 +* 数据库索引 +* 倒排索引(Inverted Index) +* 双层桶划分 +* 外排序 +* simhash算法 +* 分布处理之Mapreduce + + ### 估算 在处理海量问题之前,我们往往要先估算下数据量,能否一次性载入内存?如果不能,应该用什么方式拆分成小块以后映射进内存?每次拆分的大小多少合适?以及在不同方案下,大概需要的内存空间和计算时间。 @@ -32,7 +44,7 @@ IP地址 -### 分而治之/Hash映射 +### Hash映射/分而治之 这里的`Hash映射`是指通过一种映射散列的方式,将海量数据均匀分布在对应的内存或更小的文件中 @@ -298,16 +310,144 @@ trie树的增加和删除都比较麻烦,但索引本身就是写少读多, ### 数据库索引 -数据库索引一般使用B树(B+树,R树)实现。 +索引使用的数据结构多是B树或B+树。B树和B+树广泛应用于文件存储系统和数据库系统中,mysql使用的是B+树,oracle使用的是B树,Mysql也支持多种索引类型,如b-tree 索引,哈希索引,全文索引等。 + +一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。 + + +##### 磁盘数据查找过程 + +![](disk_search.png) + +盘面:每一个盘片都有2个上下盘面,每个盘面都可以存储数据 + +柱面:所有盘面上的同一磁道构成一个圆柱,叫做柱面。磁盘读写按柱面进行; +只在同一柱面所有的磁头全部读/写完毕后磁头才转移到下一柱面,因为选取磁头只需通过电子切换即可,而选取柱面则必须通过机械切换。电子切换相当快,比在机械上磁头向邻近磁道移动快得多,所以,数据的读/写按柱面进行,而不按盘面进行。也就是说,一个磁道写满数据后,就在同一柱面的下一个盘面来写,一个柱面写满后,才移到下一个扇区开始写数据。读数据也按照这种方式进行,这样就提高了硬盘的读/写效率。 + +磁道:磁盘在格式化时被划分出许多同心圆,这些同心圆轨迹叫做磁道 track。磁道从外向内从0开始编号。 + +扇区:信息以脉冲串的形式记录在这些轨迹中,这些同心圆不是连续记录数据,而是被划分成一段段圆弧,每段圆弧叫做一个扇区,扇区从“1”开始编号 。扇区也叫块号。 + +磁盘在物理上划分为柱面, 磁道,扇区。想要读取扇区的数据,需要将磁头放到这个扇区上方: + +1. 先找到柱面,也就是寻道。磁头是不能动的,但可以沿着磁盘半径方向运动,耗时记为寻道事件 t(seek) +2. 将目标扇区旋转到磁头下,这个过程耗时是旋转时间t(r) + +一个磁盘扇区数据读取的时间t = t(seek)+t(r)+t(数据传输) , 在数据库查找数据时,查找时间与访问的磁盘盘块成正比,内存处理时间可以忽略不计。 + + +##### B树 + +2-3树:一个节点最多有2个key,红黑树就是2-3树的一种实现。 + +B树又叫多路平衡查找树。B树可以看做是对2-3树的扩展,允许每个节点有M-1个key,并以升序排列,这里的M就是B树的阶。 + + +B树的度d(d>=2) ,有一些特征: + +1. 根节点至少有2个子节点 +2. 所有的叶节点具有相同的深度 h,也就是树高 +3. 每个叶子节点至少包含一个key和2个指针,最多2d-1个key和2d个指针,叶节点的指针都是null。每个节点的关键字个数在【d-1,2d-1】之间 +4. 每个非叶子节点,key和指针互相间隔,节点两端是指针,因此节点中指针个数=key的个数+1 +5. 每个指针要么是null,要么指向另一个节点 + +如果某个指针在节点node最左边且不为null,则其指向节点的所有key小于v(key1),其中v(key1)为node的第一个key的值。 +如果某个指针在节点node最右边且不为null,则其指向节点的所有key大于v(keym),其中v(keym)为node的最后一个key的值。 +如果某个指针在节点node的左右相邻key分别是keyi和keyi+1且不为null,则其指向节点的所有key小于v(keyi+1)且大于v(keyi)。 + + +使用数据结构表示如下: + +``` +typedef struct Item{ + int key; + Data data; +} + +#define m 3 //B树的阶 + +typedef struct BTNode{ + int degree; //B树的度 + int keynums; //每个节点key的个数 + Item items[m]; + struct BTNode *p[m]; +}BTNode,* BTree; + +typedef struct{ + BTNode *pt; //指向找到的节点 + int i; // 节点中关键字的序号 (0,m-1) + int tag; //1:查找成功,0:查找失败 +}Result; + +Status btree_insert(root,target); +Status btree_delete(root,target); +Result btree_find(root,target); + +``` + +##### 建立索引 + +当为一张空表创建索引时,数据库系统将为你分配一个索引页,该索引页在你插入数据前一直是空的。此页此时既是根结点,也是叶结点。每当你往表中插入一行数据,数据库系统即向此根结点中插入一行索引记录。 + +插入和删除新的数据记录都会破坏B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质 + +##### 查找操作 + +从root节点出发,对每个节点,找到等于target的key,则查找成功;或者找到大于target的最小k[i], 到 k[i] 左指针指向的子节点继续查找,直到页节点,如果找不到,说明关键字target不在B树中。 + +分析下时间复杂度: + +对于一个度为d的B-Tree,每个节点的索引key个数是d-1, 索引key个数为N,树高h上限是: + +2d^h-1=N ==> h=logd^((N+1) /2) ??? + +因此,检索一个key,查找节点的个数的复杂度是O(logd^N) + +``` +比如d=2,N=1,000,000 (1百万),h差不多20个 +d=3,N=1,000,000 (1百万) ,h差不多13个(3^11=1,594,323) +d=4,N=1,000,000 (1百万) ,h差不多10个 +d=5,N=1,000,000 (1百万) ,h差不多9个 (5^9 = 1,953,125) +d=6,N=1,000,000 (1百万) ,h差不多8个(6^8 = 1,679,616) +d=7,N=1,000,000 (1百万) ,h差不多8个 +d=8,N=1,000,000 (1百万) ,h差不多7个 +d=9,N=1,000,000 (1百万) ,h差不多7个 +d=10,N=1,000,000 (1百万) ,h差不多6个 +d=100时,h差不多3个 +``` + +数据库系统在设计时,通常将一个节点的大小设为一个页大小(通常4k),这样保证一个节点在物理上也存储在一个页里,加上计算机存储分配都是按页对其,这样保证一个节点只需要一次I/O. + +实际应用中,d都是比较大,通常超过100,因此1百万的数据通常最多访问3个节点,也就是3次I/O, 因此使用B树作为索引结构查询效率非常高。 + + +##### 插入数据 + +插入数据时,需要更新索引,索引中也要添加一条记录。索引中添加一条记录的过程是: + +沿着搜索的路径从root一直到叶节点 + +每个节点的关键字个数在【d-1,2d-1】之间,当节点的关键字个数是2t-1时,再加入target就违反了B树定义,需要对该节点进行分裂:已中间节点为界,分成2个包含d-1个关键字的子节点(另外还有一个分界关键字,2*(d-1)+1=2d-1),同时把该分界关键字提升到该叶子的父节点中,如果这导致父节点关键字个数超过2d-1,就继续向上分裂,直到根节点。 + +如下演示动画,往度d=2的B树中插入:` 6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4` + +![](./btree_insert.gif) + + +##### B树和B+树的区别 + +B树和B+树的区别在于: + +1. B+树的非叶子节点只包含导航信息,不包含实际记录的信息,这可以保证一个固定大小节点可以放入更多个关键字,也就是更大的度d,从而树高h可以更小,从而相比B树有更优秀的查询效率 +2. 所有的叶子节点和相邻的节点使用链表方式相连,便于区间查找和遍历 +### 倒排索引(Inverted Index) -### 倒排索引(Inverted index) +也叫反向索引。是文档检索系统中最常用的数据结构。常规的索引是文档到关键词的映射,如果对应的文档是 -也叫反向索引。是文档检索系统中最常用的数据结构。 -常规的索引是文档到关键词的映射,如果对应的文档是 @@ -316,7 +456,7 @@ trie树的增加和删除都比较麻烦,但索引本身就是写少读多, 携程,58,美团的分享中都提到ES构建实时日志系统,帮助定位系统问题。 -http://es.xiaoleilu.com/index.html +[Elasticsearch权威指南](http://es.xiaoleilu.com/index.html) ### 双层桶划分 @@ -327,17 +467,18 @@ http://es.xiaoleilu.com/index.html + +### simhash算法 + + + + + ### 分布处理之Mapreduce -### Hadoop - - - - - - +##### Hadoop diff --git a/海量数据处理/btree_insert.gif b/海量数据处理/btree_insert.gif new file mode 100644 index 0000000..b6684a2 Binary files /dev/null and b/海量数据处理/btree_insert.gif differ diff --git a/海量数据处理/disk_search.png b/海量数据处理/disk_search.png new file mode 100644 index 0000000..94484cc Binary files /dev/null and b/海量数据处理/disk_search.png differ diff --git a/算法问题选编/README.md b/算法问题选编/README.md index 63cf319..59c02b8 100644 --- a/算法问题选编/README.md +++ b/算法问题选编/README.md @@ -76,12 +76,16 @@ 海量处理问题常用的分析解决问题的思路是: -* 分而治之/Hash映射 + hash统计/trie树/红黑树/二叉搜索树 + 堆排序/快速排序/归并排序 +* Hash映射/分而治之 +* Bitmap +* Bloom filter(布隆过滤器) +* Trie树 +* 数据库索引 +* 倒排索引(Inverted Index) * 双层桶划分 -* Bloom filter 、Bitmap -* Trie树/数据库/倒排索引 * 外排序 -* 分布处理之 Hadoop/Mapreduce +* simhash算法 +* 分布处理之Mapreduce ### 智力思维训练