代码改变世界

快速排序 之添加复合插入排序和原始序列取中值左pivot

2017-12-15 11:58  woodzcl  阅读(312)  评论(0编辑  收藏  举报

quicksort中,当n小于一定值时,排序效率就比直接插入排序底了,所以,此时就不要再递归下去了,直接插入排序好了;快速的原理就是因为折半递归,所以初始pivot应该有个好一点的选择,这里在原序列左右和中间序的值取中值作为pivot,位置仍然放置于左侧第一元素位置(交换)。

这就变成了工程优化的快速排序了

——————————————————————————————————————————————————

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void insertsort(int arr[], int left, int right)
{
int temp, i, j;
for (i=left+1; i<=right; i++)
{
if (arr[i]<arr[i-1])
{
temp = arr[i];
for(j=i-1; j>=left&&temp<arr[j]; j--)
{
arr[j+1] = arr[j];
}
arr[j+1] = temp;
}
}
}

int partition(int arr[], int low, int high)
{
int i = low, j = high, pivot = arr[low];
while (i<j)
{
while (i<j&&arr[j]>=pivot)
{
j--;
}
if (i<j)
{
arr[i] = arr[j];
i++;
while (i<j&&arr[i]<=pivot)
{
i++;
}
if (i<j)
{
arr[j] = arr[i];
j--;
}
}
}
arr[i] = pivot;
return i;
}

void swap(int arr[], int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

void median3_alignleft(int arr[], int left, int right)
{
int mid = (left+right)/2, k1, k2;
if (arr[left]<=arr[mid])
{
k1 = left;
k2 = mid;
}
else
{
k1 = mid;
k2 = left;
}
if (arr[right]<arr[k1])
{
k2 = k1;
}
else if (arr[right]<arr[k2])
{
k2 = right;
}
if (k2!=left)
{
swap(arr, k2, left);
}
}

void quicksort_insert(int arr[], int left, int right, int M)
{
if (right-left<=0)
{
return;
}
if (right-left+1<M)
{
insertsort(arr, left, right);
}
else
{
median3_alignleft(arr, left, right);
int pivotpos = partition(arr, left, right);
quicksort_insert(arr, left, pivotpos-1, M);
quicksort_insert(arr, pivotpos+1, right, M);
}
}

void main()
{
int arr[] = {99, 29, 17, 11, 36, 55, 47, 2, 3, 8, 12, 66};
int len = sizeof(arr)/sizeof(int);

quicksort_insert(arr, 0, len-1, 5);

for(int i=0; i<len; i++)
{
printf("%d ", arr[i]);
}

printf("\n");
}

 

//result

# ./sort
2 3 8 11 12 17 29 36 47 55 66 99

 

Finally:

M可以固定取值5-25之间任意数

这个可以作为自实现算法库来保留了,你的C工程里最好能有它。