社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
通过一趟排序将要排序的数据分割成独立的两个部分,一部分的所有数据都比另一部分所有的数据都要小,然后按照此方法对这两部分的数据分别进行快速排序,整个排序的过程可以递归进行,以此将整个数据变成有序的序列。
假如我们现在要对“6 1 2 7 9 3 4 5 10 8” 这10个数进行排序,在上一篇中我们采用冒泡排序将相邻元素比对并做调整,这样的结果是要进行很多次比对,而且每次调整局限在两个相邻元素互换位置。而本篇介绍的快速排序采用计算机领域常用的二分法思想,每次排序将数据分为两部分,交换位置也是跳跃式的,从而达到更高效率。具体思路如下:
首先选择一个元素作为基准值,比如选择第一个元素6,第一轮排序的目标是将序列中所有小于基准值的元素放在左边,所有大于基准值的元素放在右边,结果就是 1 2 5 4 3 6 7 9 10 8,第一轮实现思路如下:
我们先用变量“哨兵i”和"哨兵j“分别指向序列最左边和最右边,如下图所示:
首先哨兵j一步步向左挪动(即j- -),直到找到一个小于基准值6的数停下来,接着哨兵i一步步向右挪动(即i+ +),直到找到一个大于6的数停下。最后哨兵i指向7,哨兵j指向5,此时将两个元素位置交换。
交换后序列结果是 6 1 2 5 9 3 4 7 10 8
然后哨兵j继续向左,哨兵i继续向右,重复上面的思路,如下:
然后第二次交换后序列结果为 6 1 2 5 4 3 9 7 10 8。此时我们再重复上面的思路发现哨兵i和哨兵j都指向了数字3,说明交换到了终点,此时我们将基准值6与3对换,结果如下:
此时我们已经完成了第一轮排序的目标,数字6已经归位,小于6的都在6左边,大于6的都在6右边。此时序列被分为了两部分,然后我们分别从左边的序列(3,1,2,5,4)中选择一个基准值采用快速排序思想对左边的序列进行排序,从右边的序列(9,7,10,8)中选择一个基准值进行快速排序,如此不停分割递归排序,直到所有数都归位即完成了整个序列的排序。
public static T[] Quick_Sort<T>(T[] array, int left, int right) where T : IComparable
{
if (left>=right)
{
return array;
}
int i, j;
T temp = array[left]; //取第一个元素作为基准值
T t = default(T);
i = left; //哨兵i初始指向序列最左边
j = right; //哨兵j初始指向序列最右边
while (i != j)
{
//哨兵j向左移动,直到找到第一个比基准值小的停下
while (array[j].CompareTo(temp) >= 0 && i < j)
{
j--;
}
//哨兵i向右移动,直到找到第一个比基准值大的停下
while (array[i].CompareTo(temp) <= 0 && i < j)
{
i++;
}
if (i < j) //如果两个哨兵还没有相遇,则交换位置
{
t = array[i];
array[i] = array[j];
array[j] = t;
}
}
//将基准值归位
array[left] = array[i];
array[i] = temp;
//对左边和右边的序列分别再进行快速排序
Quick_Sort<T>(array, left, i - 1);
Quick_Sort<T>(array, i + 1, right);
return array;
}
最终调用及执行结果如下:
在最坏的情况下,快速排序也需要像冒泡排序一样每相邻两个元素都要比较,时间复杂度为O(N2),快速排序平均时间复杂度为O(NlogN)。
然后我们做一个测试,随机生成一个包含十万个数字的数组,分别用冒泡排序和快速排序对比排序所需时间。
测试代码如下:
static void Main(string[] args)
{
int[] array1 = new int[100000];
int[] array2 = new int[100000];
var rand = new Random();
for (int i = 0; i < array1.Length; i++)
{
var temp = rand.Next(100000);
array1[i] = temp;
array2[i] = temp;
}
Task.Run(() =>
{
Console.WriteLine("冒泡排序开始...");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
SortHelper.MP_Sort<int>(array1);
stopwatch.Stop();
Console.WriteLine("冒泡排序结束,十万条数据用时:" + stopwatch.Elapsed.TotalMilliseconds + "ms");
});
Task.Run(() =>
{
Console.WriteLine("快速排序开始...");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
SortHelper.Quick_Sort<int>(array2,0,array2.Length-1);
stopwatch.Stop();
Console.WriteLine("快速排序结束,十万条数据用时:" + stopwatch.Elapsed.TotalMilliseconds + "ms");
});
Console.ReadLine();
}
测试结果如下:
很明显,在数据量较大情况下,快速排序的平均效率高出冒泡排序多个数量级。
博客新人~如有问题或错误,还望大家在评论中斧正
上一篇: 排序算法——冒泡排序.net实现.
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!