快速排序的优化--三数取中法

//*********************三数取中法(快排的优化)****************************
//未优化|我们总是把数组尾元素固定为key的值,然后通过调整让key回到它正确的位置
//前快排|然后以key为中心,把数组划分为key左边和key右边两个区域,然后继续在左边
//的缺陷|和右边划分区域,直到最后区域里没有元素或者只有一个元素的时候,排序结束
//      |理想的是key的位置刚好在数组的中间,那么两边划分区域就快一点,但是如果
//      |key的值很小或者很大呢?那么左边或者右边至少有一边是没有元素的,这样效率就低了

//思路:因为key的值最好每次都能把数组分成二分的两半,所以key的值最好是区域内比较居中的
//      值,所以每次把区域内的首元素、尾元素、中间的元素做比较,选出不大不小的那个,
//      然后把选出来的这个值,交换到数组的尾部,以便调整后它能回到数组中间的位置


//取首元素和尾元素及其中间元素中不大不小的数当作key值
int GetMidNum( int * a , int left , int right )
{
                 assert ( a );
                 if ( left >= right )
                                 return -1;
                 int mid = left + ( right - left ) / 2;
                 if ( a [ left ] < a [ right ])
                {
                                 if ( a [ right ] < a [mid])
                                                 return right ;
                                 else if ( a [ left ] < a [mid])
                                                 return mid;
                                 else
                                                 return left ;
                }
                 else
                {
                                 if ( a [ left ] < a [mid])
                                                 return left ;
                                 else if ( a [ right ] < a [mid])
                                                 return mid;
                                 else
                                                 return right ;
                }
}

int PartSort( int * a , int left , int right )
{
                 //每次进来取数值比较居中的元素的位置
                 int midIndex = GetMidNum( a , left , right );

                 //保证key在需排序的区域内的右边
                swap( a [midIndex], a [ right ]);   //不能写为 swap(key, a[right])
                 int key = a [midIndex];

                 int cur = left ;
                 int prev = left - 1;
                 while (cur < right )
                {
                                 //只要a[cur] < key成立,则++prev,不管最后进不进去if循环
                                 if ( a [cur] < key && ++prev != cur)
                                {
                                                swap( a [prev], a [cur]);
                                }
                                cur++;
                }
                swap( a [ right ], a [++prev]);
                 return prev;
}

void QuickSort_OP( int * a , int left , int right )
{
                 assert ( a );
                 if ( left >= right )
                                 return ;

                 //当区域很小的时候,插入排序比快排递归效率高
                 if ( right - left   <= 20)
                {
                                InsertSort( a + left , right - left + 1);
                }
                 int mid = PartSort( a , left , right );

                QuickSort_Non( a , left , mid - 1);
                QuickSort_Non( a , mid + 1, right );
}

void QuickSort_OPTest()
{
                 int arr[] = { 2, 0, 4, 9, 3, 6, 8, 7, 1, 5 };
                 //int arr[] = { 2, 5, 4, 9, 3, 5, 8, 7, 1, 5 };
                 int _size = sizeof (arr) / sizeof (arr[0]);
                QuickSort_Non(arr, 0, _size - 1);
                Print(arr, _size);
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值