当前位置: 首页 > news >正文

深圳网站优化指导亮点网络科技有限公司

深圳网站优化指导,亮点网络科技有限公司,搜狗网址,上海 网站撤销备案概述 在上一篇文章中#xff0c;我们介绍了快速排序以及随机快速排序#xff1a; 「数组」快速排序 / 随机值优化|小区间插入优化#xff08;C#xff09; 今天#xff0c;我们来介绍归并排序。 相比于快速排序是冒泡排序融合了分治思想后形成的究极promax进化版…概述 在上一篇文章中我们介绍了快速排序以及随机快速排序 「数组」快速排序 / 随机值优化|小区间插入优化C 今天我们来介绍归并排序。 相比于快速排序是冒泡排序融合了分治思想后形成的究极promax进化版归并排序不来自任何一种使用分治的基础排序它本人就是纯粹的分治。 思路 冯·诺依曼想过这么一个事两个有序数组二路合并成一个有序数组的时间复杂度是线性的 i 0 1 2 3 4 arr1[i] 1 5 6 8 9 arr2[i] 0 2 3 4 7ans[i] 1 2 3 4 5 6 7 8 9 很明显 你只需要双指针i和j分别指向两个数组k指针指向答案数组 每次都进行ans[k]min(arr1[i],arr2[j])之后i或j这要看min函数取到了谁 就能在线性时间内得到合并好的数组。 那如果能把一个无序数组在中间一分为二成两个有序的子数组然后合并就好了但是子数组怎么能有序呢 那如果能把这两个子数组分成四个有序子数组然后合并就好了。 那如果能把这四个子数组分成八个有序子数组然后合并就好了。 ..................... 那如果能把这一个数分成诶等等一个数本来就有序啊。 那从这里再一层一层合并上去不就好了冯·诺依曼恍然大悟。 算法过程 来把我们的思路实现一遍。 merge_sort() 我们给出函数merge_sort它接收一个范围它只干两件事  ①申请一个辅助数组。 ②启动这个层层划分的过程。 让我们谈谈辅助数组: 在二路归并时我们需要一个地方承载我们的结果。那不如就让原数组承载我们的结果辅助数组[l,r)位置上拷贝一份原数组[l,r)位置上的值,两个指针i和j都指向辅助数组的对应位置然后向原数组填入对应的结果。这样我们的排序结果就还放在原来的内存地址上。 void merge_sort(int arr[], int l, int r) {int* assist new int[r-l];recursion(arr, l, r, assist);delete[] assist; } recursion() 我们给出递归函数recursion它只干两件事  ①一刀劈开接收到的数组然后传给两个子recursion。 ②在劈开的两个数组有序后启动二路合并。 *注意*根据代码语言传统l和r往往是一个左闭右开区间即[l,r表示范围取到l但取不到r。两个子数组的范围分别是[l,m),[m,r)。 void recursion(int arr[], int l, int r, int assist[]) {if (r - l 1)return;int m (l r) / 2;recursion(arr, l, m, assist);recursion(arr, m, r, assist);merge(arr, l, m, r, assist); } merge()  我们给出递归函数recursion它只干两件事  ①把原数组对应位置的数据拷贝给辅助数组的对应位置。 ②进行一个极其简单的二路合并。 *注意*i或j触底后将另一个数组的剩余部分通通接入合并后数组的末尾。 void merge(int arr[], int l, int m, int r, int assist[]) {memcpy(assist[l], arr[l], sizeof(int) * (r - l));int i, j, k;for (i l, j m, k l;; k) {if (i m || j r)break;if (assist[i] assist[j])arr[k] assist[i];else arr[k] assist[j];}while (i ! m)arr[k] assist[i];while (j ! r)arr[k] assist[j]; } Code void merge(int arr[], int l, int m, int r, int assist[]) {memcpy(assist[l], arr[l], sizeof(int) * (r - l));int i, j, k;for (i l, j m, k l;; k) {if (i m || j r)break;if (assist[i] assist[j])arr[k] assist[i];else arr[k] assist[j];}while (i ! m)arr[k] assist[i];while (j ! r)arr[k] assist[j]; } void recursion(int arr[], int l, int r, int assist[]) {if (r - l 1)return;int m (l r) / 2;recursion(arr, l, m, assist);recursion(arr, m, r, assist);merge(arr, l, m, r, assist); } void merge_sort(int arr[], int l, int r) {int* assist new int[r-l];recursion(arr, l, r, assist);delete[] assist; } 谈谈奇数 常有人对于归并排序对于奇数长度数组的可行性产生质疑。我们来思考一下这个问题。 先想想二路归并 i 0 1 2 3 4 arr1[i] 1 5 6 8 arr2[i] 0 2 3 4 7ans[i] 1 2 3 4 5 6 7 8 结合上面的merge()实现代码你能发现两个长度不同的子数组丝毫不影响二路归并的进行。 那么奇数数组导致的中间位置不均匀丝毫不会影响整个排序。 优化方案 1.if语句优化 在一些时候二路合并根本没必要发生第一个有序子数组的最后一个数比第二个有序子数组的第一个数小那么他们天然就接在了一起。 void merge_if(int arr[], int l, int m, int r, int assist[]) {if (arr[m - 1] arr[m])return;memcpy(assist[l], arr[l], sizeof(int) * (r - l));int i, j, k;for (i l, j m, k l;; k) {if (i m || j r)break;if (assist[i] assist[j])arr[k] assist[i];else arr[k] assist[j];}while (i ! m)arr[k] assist[i];while (j ! r)arr[k] assist[j]; } 2.小区间插入优化 最底层会产生大量recursion递归来对小区间二分而他们分区的范围却极小这是不必要的而且相当被动。 插入排序在小区间的表现要好于快速分区当分区小到某个程度时我们直接转发给插入排序。 void recursion_with_insertion(int arr[], int l, int r, int assist[]) {if (r - l 20){insertion_sort(arr[l], r - l); return;}int m (l r) / 2;recursion_with_insertion(arr, l, m, assist);recursion_with_insertion(arr, m, r, assist);merge_if(arr, l, m, r, assist); } Code void merge_if(int arr[], int l, int m, int r, int assist[]) {if (arr[m - 1] arr[m])return;memcpy(assist[l], arr[l], sizeof(int) * (r - l));int i, j, k;for (i l, j m, k l;; k) {if (i m || j r)break;if (assist[i] assist[j])arr[k] assist[i];else arr[k] assist[j];}while (i ! m)arr[k] assist[i];while (j ! r)arr[k] assist[j]; } void recursion_with_insertion(int arr[], int l, int r, int assist[]) {if (r - l 20){insertion_sort(arr[l], r - l); return;}int m (l r) / 2;recursion_with_insertion(arr, l, m, assist);recursion_with_insertion(arr, m, r, assist);merge_if(arr, l, m, r, assist); } void MGsort(int arr[], int l, int r) {int* assist new int[r - l];recursion(arr, l, r, assist);delete[] assist; } 复杂度 时间复杂度O(nlogn) 空间复杂度O(n) 复杂度分析 时间分析 把一个长度为n的数组一直二分成长度为1的数组的次数是logn次也就是有logn层 -------------------------------------- ----------------- -------------------- --------- ------- ------ ------------- --- ----- --- -- -- --- --- --------- - - - --- - - -- -- - - - - ---- ---- - - - - - - - - - - - - - - - - - - -- ——————————————————n——————————————————— —m——m——m——m——m——m——m——m——m——m——m——m——m 每一层都要对子数组两两二路合并复杂度为O(m)m为子数组的长度 而每一层的全体m求和为n故每一层的复杂度都为O(n)有logn层故得到O(nlogn)。 空间分析 使用了长度为n的辅助数组故为O(n)。 *注意*同一层的每次合并函数和递归函数结束后空间都会被释放下次函数都会再次占据这块空间空间复用使得每一层的复杂度都是O(1)函数的空间占用整体为O(logn) 。O(nlogn)O(n)。 总结 分而治之是为分治。 如果你的朋友问什么是分治那么就给他讲讲归并排序。作为应用分治思想的算法它真的纯粹到毫无保留。
http://www.hkea.cn/news/14460525/

相关文章:

  • 什么网站可以做长图攻略游戏门户网站模板
  • 哪个网站可以做字体大小电子商务网站建设含代码
  • 上海网站开发培训网站模板如何删除
  • 在银行网站如何做理财风险评测涂鸦app定制开发
  • 怎样搭建一个个人网站wordpress插件 stock
  • 网站更新和维护怎么做seo辉煌电商平台
  • 网站内链怎么布局tornado网站开发 教程
  • 做减肥餐的网站网站建设系统源码
  • 古镇网站建设哪家好心理学网站的建设
  • 深圳 响应式网站建设服务器网站怎么用
  • 南京网站建设耐油橡胶板网络营销方式落后的表现
  • 做快餐 承包食堂的公司网站制造企业网站的建设目标
  • 招投标建设网站的网站做个人网站要注意什么
  • 源码编辑器下载张家港优化网站seo
  • 阳西住房和城乡规划建设局网站建网站 收费标准
  • 网站建设 上传和下载功能今天重大新闻国内最新消息
  • dw设计做网站完整案例网页设计模板图片简约
  • 南通市住房和建设局网站做动漫的游戏 迅雷下载网站
  • 网站建设接单吧郑州网站建设
  • dz网站建设教程wordpress 没有添加主题
  • 昌邑市建设局网站汉阳网站建设哪家便宜
  • 企业网站多少钱一个公司管理系统软件
  • 网站建设如何搞活动公司网站的服务费做哪个科目
  • 互联网建站一个网站开发的意义
  • 网站建设设计哪家好开发一个软件需要多长时间
  • 宁波网站建设服务报价深圳定制工作装
  • 网上申请个人营业执照网站做企业网站需要什么
  • 做外贸网站注意事项wordpress论坛建设
  • 青海企业网站建设开发WordPress文章付费系统
  • 做seo的网站wordpress 模板带数据