js快速排序算法解析
2018-08-23 16:13 muamaker 阅读(2017) 评论(0) 编辑 收藏 举报数组的快速排序算法,和并归排序步骤基本类似。
都是先拆分,后合并。并归排序是:拆分容易,合并难。 快速排序是:拆分难,合并容易
要理解快速排序,首先要理解拆分逻辑
要素:找一个基准点,通过操作使得数列的左边全部都是小于他的数,右边全部都是大于他的数;
1、选中基准点,开始索引 i ,结束索引 j
2、从数列右边开始往左边找,找到比基准点小的,交换位置 i++
3、从数列左边开始往右边找,找到比基准点大的,交换位置 j--
4、循环执行2、3,直到,i 不是小于 j
例如: 有数组 var arr = [30,24,5,58,18,36,12,42,39];
开始索引 i = 0; 结束索引 j = arr.length-1; 基准点 pivot = arr[i] 即为30
则有如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | var arr = [30,24,5,58,18,36,12,42,39]; var i = 0, j = arr.length-1,pivot = arr[i]; while (i < j ){ //当最后结束时 i = j //从右往左找,找到比基准点小等的就交换,交换后,基准点的索引变为 j while (i < j && arr[j] > pivot ) j--; //排除已经满足条件的点 if (i < j ){ swap(i++,j,arr); } //从左往右找,找到比基准点大的就交换,交换后,基准点的索引变为 i while (i < j && arr[i] <= pivot) i++; //排除已经满足条件的点 if (i < j ){ swap(i,j--,arr); } } function swap(a,b,arr){ console.log(a,b,arr[a],arr[b]) var temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } console.log(i,arr); //基准点i,处理好的arr |
以上代码就是快速排序的核心,如果将数列,不断以上面方式细分,直到分为单个元素。即最后的结果就是一个有序的数列
下面给出完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | var arr = [30,24,5,58,18,36,12,42,39]; function Partition(arr,low,high){ var i = low,j = high,pivot = arr[i]; while (i < j ){ //从右往左找 while (i < j && arr[j] > pivot ) j--; if (i < j ){ swap(i++,j,arr); } //从左往右找 while (i < j && arr[i] <= pivot) i++; if (i < j ){ swap(i,j--,arr); } } return i; //返回基准元素位置 } function swap(a,b,arr){ console.log(a,b,arr[a],arr[b]) var temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } function QuickSort(arr,low,high){ var mid; if (low < high){ mid = Partition(arr,low,high); //返回基准元素位置 QuickSort(arr,low,mid-1); //左边快速排序 QuickSort(arr,mid+1,high); //右边快速排序 } } QuickSort(arr,0,arr.length-1); console.log(arr); |
优化扩展:
上面的Partition函数中,不管是从右往左,还是从左往右。都是跟pivot基准元素交换。。实际上,可以先直接左边和右边交换,最后再和基准元素交换,减少交换次数。代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | var arr = [30,24,5,58,18,36,12,42,39]; var i = 0, j = arr.length-1,pivot = arr[i]; var mid; while (i < j ){ //当最后结束时 i = j //从右往左找 while (i < j && arr[j] > pivot ) j--; //排除已经满足条件的点 //从左往右找 while (i < j && arr[i] <= pivot) i++; //排除已经满足条件的点 //找到两个点,就相互交换 if (i < j ){ swap(i++,j--,arr); } } //最后将中间点和基准点交换 if (arr[i] > pivot){ mid = i-1; swap(0,mid,arr); } else { mid = i; swap(0,mid,arr); } function swap(a,b,arr){ console.log(a,b,arr[a],arr[b]) var temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } console.log(mid,arr); //基准点mid,处理好的arr |
使用js的数组方法 , unshift 和push
使用unshift 和push实现,将数列的基准元素,左边全部小于他,右边全部大于他
1 2 3 4 5 6 7 8 9 10 11 | var arr = [30,24,5,58,18,36,12,42,39]; var i = 0, pivot = arr[0], arr2 = [pivot]; for ( var j = 1; j < arr.length; j++ ){ if (arr[j] > pivot){ arr2.push(arr[j]); } else { arr2.unshift(arr[j]); i++; } } console.log(i,arr2); |
使用 unshift和push实现的快速排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | var arr = [30,24,5,58,18,36,12,42,39]; function Partition(arr,low,high){ var i = low,pivot = arr[i]; var arr2 = [pivot]; for ( var j = low+1; j <= high; j++){ if (arr[j] > pivot){ arr2.push(arr[j]); } else { arr2.unshift(arr[j]); i++; } } j = 0; for ( var k = low ; k <= high ; k++){ arr[k] = arr2[j++]; } return i; //返回基准元素位置 } function QuickSort(arr,low,high){ var mid; if (low < high){ mid = Partition(arr,low,high); //返回基准元素位置 QuickSort(arr,low,mid-1); //左边快速排序 QuickSort(arr,mid+1,high); //右边快速排序 } } QuickSort(arr,0,arr.length-1); console.log(arr); |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步