快速排序
来源:互联网 发布:集线器端口的电涌 编辑:程序博客网 时间:2024/06/03 19:10
快速排序
思想:
快速排序的思想巧秒,利用分治的思想,可以极快排序数组。其基本思想分两步:
1. 给你一个数组,让你选择数组中的任意一个数作为基数,然后让数组中所有比基数小的数都放在放在基数的左边,所有比基数大的数放在基数的右边。
2. 将刚才基数的位置作为中点,将数组中基数左边的所有元素做1操作,将基数右边的所有元素做1操作。
看到步骤2,就很容易想到这里面是递归调用的。所以我们的关键任务就是如何让第一步高效快速实现。
代码:
先看代码,我们来实现步骤1:
// 选n为基准, 使左边的数都比它下, 右边的数都比它大// 返回基准在数组中的位置int insertToMid(int arr[], int left, int right, int n){ int i = left; int j = right; while (i < j) { for (; i < j; --j) { if (arr[j] < n) { arr[i] = arr[j]; ++i; break; } } for (; i<j; ++i) { if (arr[i] > n) { arr[j] = arr[i]; --j; break; } } } arr[i] = n; return i;}
解释一下:选取的基数是n,是外部传入的(后面可以看到其实是数组中的第一个元素)。然后让i和j分别指向数组的开头和结尾。从数组的最后开始向前找第一个比n小的数,将这个数与赋值到i位置上(比n小的数放到n的左边)。然后又从i+1位置往后找第一个比n大的数,将这个数赋值到j位置上(比n大的数放到n的右边)。(由于第一路找第一个比n小的数的时候,是总末尾开始找的,所以可以保证现在赋值的位置的右边都是比n大的数。),直到i=j的时候,就是n该放到的中间位置。然后返回i的索引位置。
看看图解:
到这里我们完成了步骤1(选取基数,排序后使基数左边的数都小于基数,让基数右边的数都大于基数,当然这里的排序不是严格的从低到高,而是一个范围大小的归类。这样基数右边的所有数都大于基数左边的数了)
然后再完成步骤2就简单了,看看代码:
//快速排序void quickSort(int arr[], int left, int right){ if (left < right) { int mid = insertToMid(arr, left, right, arr[left]); quickSort(arr, left, mid - 1); quickSort(arr, mid + 1, right); }}
解释:这里之所以让insertToMid()
返回中间值就是为了进行递归调用,将基数左边的所有数执行步骤1,右边的所有数也执行步骤1。到最后只剩两个数的时候就,就一定为有序数列了。
图解:
总结:
快速排序的时间复杂度为 O(nlog2(n)),其快慢主要区别就是在步骤1上,当然是先步骤1可以采取自己的方法,只要能达到要求就行了。这种分治的思想还是非常先进的,感觉自己明白的又多了。
提供另外一种将讲数插入中间, 使左边数都比它小, 右边数都比它大的方法, 自己琢磨一下, 代码很简洁
int partion(int A[], int left, int right){ int point = A[right]; int index = left; for(int i=index; i<=right; ++i){ if(A[i] <= point){ swap(A[i], A[index]); index++; } } return index-1;}
- 快速排序
- 快速排序
- 快速排序
- 快速排序!
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 【javascript总结】javascript类的声明
- Laravel模板引擎Blade中section的一些标签的区别介绍
- 第九周项目一--复数类中的运算符重载(续)
- unity判断网络状态
- Oracle账户解锁
- 快速排序
- 注册邮箱验证激活技术
- Eclipse 对 Java8 的支持
- [LeetCode]Compare Version Numbers
- 【CCSDS】自学总结之TCP协议与TP协议
- C++ RVO/NRVO以及move语义的影响
- Python中的eval(),exec,execfile(),compile()
- 网页加载历程详解
- 微软对撼苹果:相似的产品 不同的策略