内部网站建设、,北京到牡丹江,wordpress 自定义后台登录页面,徐州营销网站建设报价目录 前言如何理解分治算法#xff1f;分治算法应用举例分析分治思想在海量数据处理中的应用解答开篇内容小结 前言 本节课程思维导图#xff1a; MapReduce 是 Google 大数据处理的三驾马车之一#xff0c;另外两个是 GFS#xff08;hdfs#xff09; 和 Bigtable(hbase)… 目录 前言如何理解分治算法分治算法应用举例分析分治思想在海量数据处理中的应用解答开篇内容小结 前言 本节课程思维导图 MapReduce 是 Google 大数据处理的三驾马车之一另外两个是 GFShdfs 和 Bigtable(hbase)。它在倒排索引、PageRank 计算、网页分析等搜索引擎相关的技术中都有大量的应用。MapReduce 的本质就是我们今天要学的这种算法思想分治算法。
如何理解分治算法
分治算法divide and conquer的核心思想其实就是四个字分而治之 也就是将原问题划分成 n 个规模较小并且结构与原问题相似的子问题递归地解决这些子问题然后再合并其结果就得到原问题的解。 关于分治和递归的区别分治算法是一种处理问题的思想递归是一种编程技巧。实际上分治算法一般都比较适合用递归来实现。分治算法的递归实现中每一层递归都会涉及这样三个操作
分解将原问题分解成一系列子问题解决递归地求解各个子问题若子问题足够小则直接求解合并将子问题的结果合并成原问题。
分治算法能解决的问题一般需要满足下面这几个条件
原问题与分解成的小问题具有相同的模式原问题分解成的子问题可以独立求解子问题之间没有相关性这一点是分治算法跟动态规划的明显区别等我们讲到动态规划的时候会 详细对比这两种算法具有分解终止条件也就是说当问题足够小时可以直接求解可以将子问题合并成原问题而这个合并操作的复杂度不能太高否则就起不到减小算法总体复杂度的效果了。
分治算法应用举例分析
还记得我们在排序算法里讲的数据的有序度、逆序度的概念吗我当时讲到我们用有序度来表示一组数据的有序程度用逆序度表示一组数据的无序程度。 假设我们有 n 个数据我们期望数据从小到大排列那完全有序的数据的有序度就是 n(n-1)/2逆序度等于 0相反倒序排列的数据的有序度就是 0逆序度是 n(n-1)/2。除了这两种极端情况外我们通过计算有序对或者逆序对的个数来表示数据的有序度或逆序度。 我现在的问题是如何编程求出一组数据的有序对个数或者逆序对个数呢因为有序对个数和逆序对个数的求解方式是类似的所以你可以只思考逆序对个数的求解方法。 我们用分治算法来试试。我们套用分治的思想来求数组 A 的逆序对个数。我们可以将数组分成前后两半 A1 和 A2分别计算 A1 和 A2 的逆序对个数 K1 和 K2然后再计算 A1 与 A2 之间的逆序对个数 K3。那数组 A 的逆序对个数就等于 K1K2K3。 如何快速计算出两个子问题 A1 与 A2 之间的逆序对个数呢 这里就要借助归并排序算法了。归并排序中有一个非常关键的操作就是将两个有序的小数组合并成一个有序的数组。实际上在这个合并的过程中我们就可以计算这两个小数组的逆序对个数了。每次合并操作我们都计算逆序对个数把这些计算出来的逆序对个数求和就是这个数组的逆序对个数了。 上述代码实现
private int num 0; // 全局变量或者成员变量public int count(int[] a, int n) {num 0;mergeSortCounting(a, 0, n-1);return num;
}private void mergeSortCounting(int[] a, int p, int r) {if (p r) return;int q (pr)/2;mergeSortCounting(a, p, q);mergeSortCounting(a, q1, r);merge(a, p, q, r);
}private void merge(int[] a, int p, int q, int r) {int i p, j q1, k 0;int[] tmp new int[r-p1];while (iq jr) {if (a[i] a[j]) {tmp[k] a[i];} else {num (q-i1); // 统计p-q之间比a[j]大的元素个数tmp[k] a[j];}}while (i q) { // 处理剩下的tmp[k] a[i];}while (j r) { // 处理剩下的tmp[k] a[j];}for (i 0; i r-p; i) { // 从tmp拷贝回aa[pi] tmp[i];}
}分治思想在海量数据处理中的应用
分治算法思想的应用是非常广泛的并不仅限于指导编程和算法设计。它还经常用在海量数据处理的场景中。 比如给 10GB 的订单文件按照金额排序这样一个需求看似是一个简单的排序问题但是因为数据量大有 10GB而我们的机器的内存可能只有 2、3GB 这样子无法一次性加载到内存也就无法通过单纯地使用快排、归并等基础算法来解决了。
我们就可以利用分治的思想。我们可以将海量的数据集合根据某种方法划分为几个小的数据集合每个小的数据集合单独加载到内存来解决然后再将小数据集合合并成大数据集合。实际上利用这种分治的处理思路不仅仅能克服内存的限制还能利用多线程或者多机处理加快处理的速度。
上述例子给 10GB 的订单排序我们就可以先扫描一遍订单根据订单的金额将 10GB 的文件划分为几个金额区间。比如订单金额为 1 到 100 元的放到一个小文件101 到 200 之间的放到另一个文件以此类推。这样每个小文件都可以单独加载到内存排序最后将这些有序的小文件合并就是最终有序的 10GB 订单数据了。
如果订单数据存储在类似 GFS 这样的分布式系统上当 10GB 的订单被划分成多个小文件的时候每个文件可以并行加载到多台机器上处理最后再将结果合并在一起这样并行处理的速度也加快了很多。不过这里有一个点要注意就是数据的存储与计算所在的机器是同一个或者在网络中靠的很近比如一个局域网内数据存取速度很快否则就会因为数据访问的速度导致整个处理过程不但不会变快反而有可能变慢。
解答开篇
我们现在来看下开篇的问题为什么说 MapReduce 的本质就是分治思想 如果我们要处理的数据是 1T、10T、100T 这样子的那一台机器处理的效率肯定是非常低的。而对于谷歌搜索引擎来说网页爬取、清洗、分析、分词、计算权重、倒排索引等等各个环节中都会面对如此海量的数据比如网页。所以利用集群并行处理显然是大势所趋。 一台机器过于低效那我们就把任务拆分到多台机器上来处理。如果拆分之后的小任务之间互不干扰独立计算最后再将结果合并。这不就是分治思想吗 实际上MapReduce 框架只是一个任务调度器底层依赖 GFS hdfs来存储数据依赖 Borgk8s 管理机器。它从 GFS 中拿数据交给 Borg 中的机器执行并且时刻监控机器执行的进度一旦出现机器宕机、进度卡壳等就重新从 Borg 中调度一台机器执行。
尽管 MapReduce 的模型非常简单但是在 Google 内部应用非常广泛。它除了可以用来处理这种数据与数据之间存在关系的任务比如 MapReduce 的经典例子统计文件中单词出现的频率。除此之外它还可以用来处理数据与数据之间没有关系的任务比如对网页分析、分词等每个网页可以独立的分析、分词而这两个网页之间并没有关系。网页几十亿、上百亿如果单机处理效率低下我们就可以利用 MapReduce 提供的高可靠、高性能、高容错的并行计算框架并行地处理这几十亿、上百亿的网页。
内容小结
今天我们讲了一种应用非常广泛的算法思想分治算法。分治算法用四个字概括就是“分而治之”将原问题划分成 n 个规模较小而结构与原问题相似的子问题递归地解决这些子问题然后再合并其结果就得到原问题的解。这个思想非常简单、好理解。 今天我们讲了两种分治算法的典型的应用场景一个是用来指导编码降低问题求解的时间复杂度另一个是解决海量数据处理问题。比如 MapReduce 本质上就是利用了分治思想。