文章目录
- 总览
- 快速排序(超级重要)
- 啥是快速排序
- 演示过程
- 算法实现
- 第一次quicksort函数
- 第一次partion函数
- 到第一次quicksort的第一个quicksort
- 到第二次quicksort的第一个quicksort
- 到第二次quicksort的第二个quicksort
- 到第一次quicksort的第二个quicksort
- 到第一次quicksort的第二个quicksort的partition
- 到第一次quicksort的第二个quicksort的第一个quicksort
- 到第一次quicksort的第二个quicksort的第一个quicksort的partition函数
- 到第一次quicksort的第二个quicksort的第一个quicksort的第一个quicksort函数
- 到第一次quicksort的第二个quicksort的第一个quicksort的第二个quicksort函数
- 到第一次quicksort的第二个quicksort的第二个quicksort
- 第一次quicksort的第二个quicksort执行完
- 第一个quicksort执行完
- 算法效率分析
- 最好的情况
- 最坏的情况
- 优化
- 算法效率小结
- 稳定性
- 小结
总览
快速排序(超级重要)
啥是快速排序
演示过程
此时选49为枢轴元素,接着low和high往中间移动,并且保证,low左边都是小于枢轴元素,high元素右边都是大于枢轴元素
此时high位置的49大于等于49,high左移
此时high所指的元素为27小于49,所以将high位置的元素移动到low位置
移动后,high的位置空出来,此时移动low位置,此时low的位置的元素为27,小于49,low移动
此时low位置的元素依然小于49,low移动
此时low指向的元素65大于49,移动到high位置
此时low位置空了,移动high位置,此时high位置的元素大于49,high左移
此时high位置元素13小于49,13移动到low位置,
此时high空,移动low,此时13小于49,low右移
此时97大于49,将97移动到high
此时移动high,97大于49,high左移
此时76大于49,high左移
low和high碰到一起,此时左右元素都扫了一遍了,比49都小的元素都放到low的左边了,比49大的元素都放high的右边,
然后把枢轴元素放到low和high重合的位置
接下来对分别对左右两个子表进行刚刚的过程
此时是左子表,high位置元素13小于27,移动到low
此时移动low,13小于27,low右移,
此时38大于27,38移到high
此时移动high,38大于27,high左移
此时high和low重合,27放入该位置
此时该子表又划分两个子表,此时两个子表都只有一个元素,此时不需要处理,因为此时low左边元素小于枢轴,high右边元素大于枢轴,又因为此时左右都只有一个元素,所以已经有序
此时要处理右子表,high所指元素49小于76,49移动到low,
此时49小于76,low右移动
此时97大于76,97移动到high
此时high移动,97大于76,high左移
65小于76,65移动到low
low移动,65小于76,low右移,
low和high碰头,76放入该位置
此时再次划分为两个子表,对左子表处理
此时65大于49,high左移
low和high碰头,49放该位置
此时由于65和97都只有一个元素,所以直接确定位置
最后排序结果
算法实现
首先调用QuickSor函数,开始对整个表划分,并调用partition函数,此时划分整个表
第一次quicksort函数
第一次partion函数
pivot就是枢轴的意思
此时partion函数大循环的条件是low<high,当low=high时将停止循环
此时大循环中还有两个循环,先是high位置开始的循环,然后是low开始的循环
发现49大于要枢轴值
high左移
此时27小于枢轴值
跳出while循环,并将此时的high的值赋值给low位置
此时跳到下一个while循环,比较low位置的值和枢轴的值,如果low的值小于枢轴的值,此时low往后移动
此时直到65发现low的值大于枢轴的值,跳出循环
此时移动low位置的值到high位置上去,此时回到大循环,发现low<high,继续下一次大循环,但大循环仍然是在溢依次分表之中
此时继续开始第一次小循环,到13跳出第一次小循环,并将high位置的值给low位置的值
此时开始第二次小循环,到97跳出第二次小循环,并将low值给high位置的值,然后进入下次大循环
此时进入第一次小循环,此时当high移动到与low相同才跳出第一次小循环,此时由于low=high,第二次小循环也会跳出,随后大循环条件不满足了,跳出大循环
然后将枢轴元素放到low的位置,并return low的值那么就完成了一次划分的工作
此时quicksort函数中pivotpos的值为该次划分的枢轴的位置
到第一次quicksort的第一个quicksort
此时处理之前划分的左子表,从low到之前返回得到的枢轴的位置
此时函数执行过程与之前类似,此时partition函数返回27,返回到第二次quicksort函数中
到第二次quicksort的第一个quicksort
此时的low和high相等,直接跳出if语句
到第二次quicksort的第二个quicksort
此时low依然等于high,直接跳出if
到第一次quicksort的第二个quicksort
此时low=3+1=4,high=7
到第一次quicksort的第二个quicksort的partition
执行过程于之前相同
结果
到第一次quicksort的第二个quicksort的第一个quicksort
此时之前的partition返回到pivotpos为6
此时的quicksort处理的low为4,high为6-1=5
到第一次quicksort的第二个quicksort的第一个quicksort的partition函数
此时结果
到第一次quicksort的第二个quicksort的第一个quicksort的第一个quicksort函数
此时之前的partition返回的pivotpos为4
则第一个quicksort对呀的low和4,high为4-1=3
此时不满足low<high,跳出if语句
到第一次quicksort的第二个quicksort的第一个quicksort的第二个quicksort函数
此时low=4+1=5,high=5,不满足low<high,跳出if语句
到第一次quicksort的第二个quicksort的第二个quicksort
此时low=6+1=7,high=7,同样不满足low<high,会跳出if
第一次quicksort的第二个quicksort执行完
第一个quicksort执行完
排序完成
算法效率分析
函数每次先得到该范围的枢轴的位置,然后再以该枢轴为中级元素分开两个范围,对各个范围进行函数
partion函数需要通过low和high将该范围的数据都遍历一遍,因为终止条件是low=high
此时空间复杂度为调用过程中调用函数栈最多的时候
每层quicksort都是上一层quicksort分成的子表处理,每层处理都分成两个子表
递归层数就是二叉树的层数
最好的情况
最坏的情况
此时high需要左移low才行,第一层quicksort处理后,第二层只需对右边部分处理
此时依然high需要移到low
第二层处理后,第三层只需对右边部分处理
按照这样,需要8层quicksort调用
如果是逆序,第一层quicksort后,ow移动到最右边的位置即high位置,第二层都只需要处理左边部分,,之后的处理类似
优化
即让枢轴的值极可能不要是最大值或最小值
算法效率小结
实际情况实际复杂度都接近于最好时间复杂度
稳定性
看这个例子
是不稳定的
小结
下图时间复杂度最好和最坏写反了