快速排序(举例为从小到大排列)
特性:
在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它采用的是内部循环(inner loop),这个可以在大部分的架构上很有效率地被实现出来。
时间复杂度:
最优: 每一次的flag刚好都可以平分整个数组,此时的时间复杂度为O(nlogn)
最坏: 每一次的flag刚好都是最大或者最小的数,此时的时间复杂度为O(n2)
平均: O(nlogn)
原理
每次扫描 碰到比基准值小的放到左边 碰到比基准值大的放到右边, 等左右两边的flag相遇时,将基准值赋值给当前的index对应的数据.
然后 接下来 进入递归 缩小范围
左边递归范围: left ->基准值赋值的index - 1
右边递归范围: 基准值赋值的index + 1 => right
简单来说就是 确保每次范围内的扫描结果是 左边小右边大,范围的获取是基于上次递归后的基准赋值index分割.
代码
+ (void)quickSortWithArray:(NSMutableArray<NSNumber *> *)array
left:(NSInteger)left
right:(NSInteger)right {
if (left > right) {
// 没得分区了,分区递归结束
return;
}
NSInteger leftIndex = left;
NSInteger rightIndex = right;
定义一个基准数据
NSInteger key = array[leftIndex].integerValue;
while (leftIndex < rightIndex) {
// 左边固定,从右边向左边扫描, 如果扫描的数据 < key 进行交换
if (leftIndex < rightIndex && key <= array[rightIndex].integerValue) {
rightIndex--;
}
if (leftIndex < rightIndex) {
array[leftIndex] = array[rightIndex];
}
// 右边固定, 从左边向右边扫描, 如果左边的数据 <key 进行交换
if (leftIndex < rightIndex && array[leftIndex].integerValue <= key) {
leftIndex++;
}
if (leftIndex < rightIndex) {
array[rightIndex] = array[leftIndex];
}
// 依次循环 直到此次内部排列 leftIndex == rightIndex 进入下一个递归
}
array[leftIndex] = [NSNumber numberWithInteger:key];
// 递归排列leftIndex左边的顺序
[self quickSortWithArray:array left:left right:leftIndex - 1];
// 递归排列rightIndex右边的顺序
[self quickSortWithArray:array left:leftIndex + 1 right:right];
}