快速排序(QuickSort):
思路:
递归二分,每次分出大小组(大组所有的数大于小组),然后递归处理大小组
具体实现:
-选择第一个元素为基准,以此为分组标准
-使用两个游标(left和right)来往中间逼近,两个游标把整个序列分成三个部分,小者区,待考察区和大者区
-算法为了减少整体移动,巧妙的利用了把第一个元素(基准)读取到变量以后留出的空位,
-在最开始的时候,left指向的位置为空位,我们需要找较小的数来放到left的位置上来扩大小者区,所以可以移动right(从尾巴上往前找)来找比基准小的数,找到了就把数放到left指向的位置,把right指向的位置空出来
-上一步之后,left指向的位置就满了,right指向的位置则空了,就不能再查找较小的数了,要查较大的数了.
-接下来就应该移动left游标来找比基准大的数,找到了就把数放到right指向的位置,
-可以理解为有空位的游标需要数,有权利移动对方来找合适的数来填满自己,填满之后就转移权力给对方,
-类似乒乓,游标像是
两个一步步走走近的磁铁, 空肚子磁铁站着不动,吸着对方往前走,直到对方能给自己一个合适的数
-直到两个游标汇合,说明都比较过了,就结束了
void qsort(int* data, int head, int tail)
{
if (head >= tail) {
return;
}
int left = head;
int right = tail;
int key = data[left];//挑选第一个元素作为分组标准(基准),并且空出一个位置出来
while (left < right) {
// 找一个比基准小的数放到空位上来
while (left < right && data[right] >= key) {// 注意比较之处需要时等号,否则会卡住
--right;// 移动游标,把大的留在大者组
}
data[left] = data[right];//把小的数放到空位上去,腾出一个空位来
// 找一个比基准大的数放到空位上来
while (left < right && data[left] <= key) {
++left;// 移动游标,把小的留在小者组
}
data[right] = data[left];
}// 如果left和right碰头了,那么说明都比较过了,可以结束了,此时left等于right
data[left] = key; // 把基准放回去
qsort(data, head, left - 1);
qsort(data, left + 1, tail);
}
因为每次分组标准的这个数的挑选有很大的标准,对性能的影响会比较大,
最理想的情况复杂度是O(nlogn),此时每次分组是最高效的等分,
最糟糕的情况是O(n2),此时分组效率最低,分组基准就是最大或者最小值,也就是已经排好序的队列