快速排序与并行快速排序分析

快排逻辑

快速排序是编程常用的排序方式,下面是快速排序的核心逻辑

 static void QuicksortSequential<T>(T[] arr, int left, int right) where T : IComparable<T>
 {
     if(right > left)
     {
         //pivot 左边的值小于arr[pivot].右边的值大于arr[pivot]
         int pivot = Partition(arr, left, right);
         //排序左边
         QuicksortSequential(arr, left, pivot - 1);
         //排序右边
         QuicksortSequential(arr, pivot + 1, right);
     }
 }

这里的快速排序使用了递归的方式,可以发现排序左边和排序右边是互不影响的,这给并行运算提供了可行性,

并行快排逻辑

static void QuicksortParallel<T>(T[] arr,int left,int right)where T:IComparable<T>
{
     if (right > left)
     {
         //防止线程开设过多反而速度变慢
         if (right - left < SEQUENTIAL_THRESHOLD)
         {
             QuicksortSequential(arr, left, right);
         }
         else
         {
             int pivot = Partition(arr, left, right);
             //并行运算
             Parallel.Invoke(new Action[] {
                 () => QuicksortParallel(arr,left,pivot - 1),
                 () => QuicksortParallel(arr,pivot + 1,right)
             });
         }
     }
 }

每开一个线程同样会造成性能的消耗,由于CPU核心数的限制,线程数超过一定数量反而会照成性能下降,所以加了一个SEQUENTIAL_THRESHOLD参数。使得要排序的单位小于他使,自动使用非并行的快速排序
附上所有代码

public class ParalleSort
{
    const int SEQUENTIAL_THRESHOLD = 2048;
    //快速排序
    public static void QuicksortSequential<T>(T[] arr)where T:IComparable<T>
    {
        QuicksortSequential(arr, 0, arr.Length - 1);
    }
    //并行快速排序
    public static void QuicksortParallel<T>(T[] arr)where T : IComparable<T>
    {
        QuicksortParallel(arr, 0, arr.Length - 1);
    }
    /// <summary>
    /// 快排逻辑
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="arr"></param>
    /// <param name="left"></param>
    /// <param name="right"></param>
    static void QuicksortSequential<T>(T[] arr, int left, int right) where T : IComparable<T>
    {
        if(right > left)
        {
            //pivot 左边的值小于arr[pivot].右边的值大于arr[pivot]
            int pivot = Partition(arr, left, right);
            //排序左边
            QuicksortSequential(arr, left, pivot - 1);
            //排序右边
            QuicksortSequential(arr, pivot + 1, right);
        }
    }
    /// <summary>
    /// 并行排序逻辑
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="arr"></param>
    /// <param name="left"></param>
    /// <param name="right"></param>
    static void QuicksortParallel<T>(T[] arr,int left,int right)where T:IComparable<T>
    {
        if (right > left)
        {
            //防止线程开设过多反而速度变慢
            if (right - left < SEQUENTIAL_THRESHOLD)
            {
                QuicksortSequential(arr, left, right);
            }
            else
            {
                int pivot = Partition(arr, left, right);
                //并行运算
                Parallel.Invoke(new Action[] {
                    () => QuicksortParallel(arr,left,pivot - 1),
                    () => QuicksortParallel(arr,pivot + 1,right)
                });
            }
        }
    }
    /// <summary>
    /// 区分数组大小值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="arr"></param>
    /// <param name="low"></param>
    /// <param name="high"></param>
    /// <returns></returns>
    static int Partition<T>(T[] arr,int low,int high)where T:IComparable<T>
    {
        int pivotPos = (high + low) / 2;
        T pivot = arr[pivotPos];
        Swap(arr, low, pivotPos);
        int left = low;
        for(int i = low + 1; i <= high; i++)
        {
            if (arr[i].CompareTo(pivot) < 0)
            {
                left++;
                Swap(arr, i, left);
            }
        }
        Swap(arr, low, left);
        return left;
    }
    /// <summary>
    /// 交换
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="arr"></param>
    /// <param name="i"></param>
    /// <param name="j"></param>
    static void Swap<T>(T[] arr,int i,int j)
    {
        T tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

测试性能

使用10000000个随机大小的数,分别使用快速排序,和并行快速排序,输出其消耗时间

const int arrayNum = 10000000;
int[] arr = new int[arrayNum];
Random random = new Random();
for(int i = 0; i < arrayNum; i++)
{
    arr[i] = random.Next(0, arrayNum);
}
var arr2 = (int[])arr.Clone();
Stopwatch w = new Stopwatch();
w.Start();
ParalleSort.QuicksortSequential(arr2);
w.Stop();
Console.WriteLine("快排序:{0}mm", w.ElapsedMilliseconds);
w.Reset();
w.Start();
ParalleSort.QuicksortParallel(arr);
w.Stop();
Console.WriteLine("并行排序:{0}mm", w.ElapsedMilliseconds);

输出如下
在这里插入图片描述
可以看到并行快排比普通快排快了4倍多

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值