游乐项目 - 1 - qsort分析以及代码实现
首先明白,流程是在不断重复 [排序分区] 这一过程的
分区过程,将比这个数大的全放到它右边,小于或等于它的全放到它的左边。
再对左右区间重复第二步,直到各区间只有一个数。
Step-1:
假设现在以这样的数组进行排序分区:
(1).首先将a[0]备份,再定义出一个i=0 -> 下界,一个j=长度-1 ->上界 (2).从后开始向前,找一个小于等于X的数,[8]号,将[8]号存到[0]号位置上 -伴随执行i++- (3).从前开始向后,找一个大于X的数字,[3]号,将3号内容放到[8]号位置 -伴随执行j-- -
Step-2:
- 执行完一次前后遍历于是此时数组变成了:
重点-1:为什么要一个从后往前,一个从前往后?
从后往前,找比X小的,因为我们目的是让后面都是大的数,所以我们从后面挑走小的,留下大的
从前往后,找到比X大的,因为我们目的是让前面都是小的数,所以从前面挑走大的,留下小的
重点-2:那为什么要执行i++ 与 j–呢? i与j的意义是什么
从后向前寻找小数的时候,每向前遍历一格,就执行一次j- -,上界减一
从前向后寻找大数的时候,每向后遍历一格,就执行一次i++,下界加一
j–与i++代表了上下界以外的数都是合格的,不用再检阅了
这样一来,下次再遍历的时候,就跳过界外的元素了
验证
我们在从后向前遍历的时候,移动了一个小格,这代表后两格已检查,下次从倒数第三个开始
我们在从前向后遍历的时候,移动了两个小格,同样的,前三格已检查,下次从第四格开始
i =3 ; j=7 ; X仍是一开始选择的基准:72
Step - 3:
重复步骤,直到上界等于下界,从下图可以看见,左边都是小数,右边都是大数
int AdjustArray(int s[], int l, int r)
{
int i = l, j = r;
int x = s[l]; // 这里出现了X,也就是本次调整的基准数
while (i < j)
{
//-----------------------------------------------------------------------
while(i < j && s[j] >= x) //从后向前遍历,每走一格,上界减一
j--;
if(i < j)
{
s[i] = s[j]; //找到了以后开始向前移动
i++;
}
//-------------------------------------------------------------------
while(i < j && s[i] < x) //从前向后遍历,每走一格,下界加一
i++;
if(i < j)
{
s[j] = s[i];
j--;
}
}
s[i] = x; //做到最后i=j,则将预先存好的X补到这里,一次排序分区完成
return i;
}
void quick_sort1(int s[], int l, int r)
{
if (l < r)
{
int i = AdjustArray(s, l, r);
quick_sort1(s, l, i - 1); // 一次排序完成以后对前半段再次执行排序分区
quick_sort1(s, i + 1, r); // 这是对后半段执行排序分区
}
}
Qsort的时间复杂度:
最好 O(n)
期望O(n*log n)
最差 O(n^2)