下一个划分级别是处理上一级别产生的子表,按照相同的处理方法分别处理左子表和右子表,左子表索引位置[0,5),右子表索引位置[6,10),按照上面的处理步骤处理左子表(400,150,300,450,350)得到的最终结果为:150,300,400,450,350 右子表最终处理结果为:550,650,800,900 在处理结果中300与650分别是中心值,他们现在的位置就是最终位置
在接下来的处理中,总是处理上一步骤中留下的子表,当子表数目<=1的时候就不用处理子表了,而子表有两个元素的时候,比较大小,然后交换两元素位置即可。
大于2个元素的子表都和上面的处理步骤一样,我们将上面的处理过程编写出一个函数
private int PivotIndex(int[] v, int first, int last),那么快速排序算法就是对此函数的递归调用
/// <summary>
/// 交换位置
/// </summary>
/// <param name="v"></param>
/// <param name="index1"></param>
/// <param name="index2"></param>
private void Swrap(int[] v, int index1, int index2)
{
int temp = v[index1];
v[index1] = v[index2];
v[index2] = temp;
}
/// <summary>
/// 将向量V中索引{first,last)划分成两个左子表和右子表
/// </summary>
/// <param name="v">向量V</param>
/// <param name="first">开始位置</param>
/// <param name="last">结束位置</param>
private int PivotIndex(int[] v, int first, int last)
{
if (last == first)
{
return last;
}
if (last - first == 1)
{
return first;
}
int mid = (first + last) / 2;
int midVal = v[mid];
//交换v[first]和v[mid]
Swrap(v, first, mid);
int scanA = first + 1;
int scanB = last - 1;
for (; ; )
{
while (scanA <= scanB && v[scanA] < midVal)
{
scanA++;
}
while (scanB > first && midVal <= v[scanB])
{
scanB--;
}
if (scanA >= scanB)
{
break;
}
Swrap(v, scanA, scanB);
scanA++;
scanB--;
}
Swrap(v, first, scanB);
return scanB;
}
public void Sort(int[] v, int first, int last)
{
if (last - first <= 1)
{
return;
}
if (last - first == 2)
{
//有两个元素的子表
if (v[first] > v[last - 1])
{
Swrap(v, first, last - 1);
}
return;
}
else
{
int pivotIndex = PivotIndex(v, first, last);
Sort(v, first, pivotIndex);
Sort(v, pivotIndex + 1, last);
}
}
快速排序因为每次划分都能将中心值元素找到最终的位置,并且左边值都小于中心值,右边都大于中心值,它的时间复杂度平均和归并算法一致为O(nlog2n);
任何一种基于比较的排序算法的时间复杂度不可能小于这个数,除非不使用比较的方法进行排序。
注:相关教程知识阅读请移步到c#教程频道。










