# 面试题目--一步步优化快速排序

#if 1
void swap(int* a, int i, int j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
void select_piovt(int *a, int start, int end)
{
int mid = (start + end)/2;

//end is max
if(a[end] < a[mid])
{
swap(a, mid , end);
}
if(a[end] < a[start])
{
swap(a, start, end);
}
//end is middle big num
if(a[mid] < a[start])
{
swap(a, end, start);
}
else
{
swap(a, end, mid);
}
}
int partition(int *a, int start, int end)
{
int p1 = start -1;
int p2 = start;
int pivot = a[end];

if(end - start > 3)
{
select_piovt(a, start, end);
}

pivot = a[end];

for(; p2 < end; ++p2)
{
if(a[p2] < pivot)
{
++p1;
swap(a, p1, p2);
}
}
swap(a, end, p1+1);
return p1+1;
}
void QuickSort(int* a, int start, int end)
{
int pivot = partition(a, start, end);

if(pivot-1 > start)
{
QuickSort(a, start, pivot - 1);
}
if( pivot+1 < end)
{
QuickSort(a, pivot+1, end);
}

}

int produce_rand_num(int n,int *a)
{
int i = 0;
srand((unsigned)time(NULL));
for(i =0 ;i < n; ++i)
{

a[i] = rand() % 10000;
printf("a[%d] = %d, ",i, a[i]);
}

return 0;
}
void printf_num_to_screem(int n , int*a)
{

int i = 0;
for(; i < n ;++i)
{
printf("%d  ", a[i]);
}
printf("\n");
}
int main()
{

int a[30] = {6,5,88,1,0,3,7,444,98,100,1,2,3,4,5,6,7,8,9,0,  9999,4,4,5,22,3333,4,5,6,4};
int size = 30;
int i = 0;

int b[100000];
//	struct timeval tpstart,tpend;
//    float timeuse;
clock_t start = 0,end = 0;

printf("there are %d nums\n", size);
QuickSort(a,0,size-1);
for(i = 0; i < size; ++i)
{
printf(" %d  ", a[i]);
}
printf("\n");
//
produce_rand_num(100000, b);

//	gettimeofday(&tpstart,NULL);
start = clock();
QuickSort(b , 0, 99999);
//	gettimeofday(&tpend,NULL);
end = clock();
//	timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ 	tpend.tv_usec-tpstart.tv_usec;
//	timeuse/=1000000;

printf_num_to_screem(100000, b);
printf("\n\nUsed Time:%f\n\n",(double)(end - start)/((long)1000 ) );
return 0;
}

#endif


0.038s

void SelectSort(int* a, int start, int end)
{
int i = 0,j = 0;
int tmp = a[start];

for(i = start +1 ; i < end ; ++i)
{
tmp = a[i];
for(j = i - 1; j>=0 && a[i] < a[j]; --j)
{
a[j+1] = a[j];
}
a[j+1] = tmp;
}
}
int partition(int *a, int start, int end)
{
int p1 = start -1;
int p2 = start;
int pivot = a[end];

if(end - start > 3)
{
select_piovt(a, start, end);
}

pivot = a[end];

for(; p2 < end; ++p2)
{
if(a[p2] < pivot)
{
++p1;
swap(a, p1, p2);
}
}
swap(a, end, p1+1);
return p1+1;
}
void QuickSort(int* a, int start, int end)
{
int pivot = 0;

if(end - start < 10)
{
SelectSort(a, start, end);
return ;
}
pivot = partition(a, start, end);

if(pivot-1 > start)
{
QuickSort(a, start, pivot - 1);
}
if( pivot+1 < end)
{
QuickSort(a, pivot+1, end);
}

}


void move_same_pivot_num(int*a, int pivot, int start, int end, int* pi_left, int* pi_right)
{
int i = 0, j = 0;
int left_num = 0;
int right_num = 0;
int key = a[pivot];

//	printf(" pivot = %d, start = %d, end = %d, \n", pivot, start, end);
if(NULL == a || NULL == pi_left || NULL == pi_right || start > end || pivot < start || pivot > end)
{
return;
}

/*  */
i = start;
j = pivot -1;
while(i < j)
{
/*从主元左边第一个数字开始寻找和主元不相同的数字，找到后停下*/
while(i < j && a[j] == key)
{
--j;
++left_num;

}
/*从数组开始的寻找第一个和主元相同的数字，找到后停下*/
while(i < j && a[i] != key)
{
++i;
}
/*将靠近主元且和主元不相同的数字 和 远离主元但和主元相同的数字 交换*/
if(i < j)
{
++left_num;
swap(a, i, j);
--j;
++i;
/*临界处理：如果前后索引指向同一个数字，即将跳出循环，若这个数字和主元相同，主元数目累加 */
if(i == j && key == a[i])
{
++left_num;
}
}
else
{
break;
}

}
/*从主元开始向左边 第一个和主元不相同数字的索引，返回，是下次排序的数组的最右边*/
*pi_left = pivot - left_num;

/*主元右边数组处理，和左边类似*/
i = pivot +1;
j = end;
while(i < j)
{
/*从数组最右边的开始寻找第一个和主元相同的数组，找到后停下 */
while(i < j && a[j] != key)
{
--j;
}
/*从主元紧挨着的第一个数字开始寻找第一个和主元不相同的数字，找到后停下 */
while(i < j && a[i] == key)
{
++i;
++right_num;

}
/*靠近主元但和主元不相同的数字  和  远离主元但和主元相同的数字  交换 */
if(i < j)
{
++right_num;
swap(a, i, j);

--j;
++i;
/*临界处理*/
if(i == j && key == a[i])
{
++right_num;
}
}
else
{
break;
}
}
/*从主元开始向右边 第一个和主元不相同数字的索引，返回，是下次排序的右边数组的最右边*/
*pi_right = pivot + right_num;
}
void QuickSort_dup_data_delete(int* a, int start, int end)
{
int pivot = 0;
int pi_left = 0, pi_right = 0;

if(NULL == a || start >= end)
return;

if(end - start <=  60)
{
SelectSort(a, start, end);
return ;
}
pivot = partition(a, start, end);
pi_left = pivot - 1;
pi_right = pivot +1;

move_same_pivot_num(a, pivot,start, end, &pi_left, &pi_right );

if(pi_left > start)
{
QuickSort_dup_data_delete(a, start,pi_left);
}
if( pi_right < end)
{
QuickSort_dup_data_delete(a, pi_right, end);
}

}

int main()
{

int a[30] = {6,5,88,1,0,3,7,444,98,100,1,2,3,4,5,6,7,8,9,0,  9999,4,4,5,22,3333,4,5,6,4};
int s[10] = {2,3,4,6,7,8,9,20,21,0};
int size = 30;
int i = 0;

int b[100000];
clock_t start = 0,end = 0;

produce_rand_num(100000, b, 100000);
start = clock();
QuickSort_dup_data_delete(b , 0, 99999);
end = clock();

printf_num_to_screem(100000, b);
printf("\n\nUsed Time:%f \n\n",(double)(end - start)/((long)1000 ) );

QuickSort_dup_data_delete(a , 0, 29);
printf_num_to_screem(30,a);

QuickSort_dup_data_delete(s , 0, 10);
printf_num_to_screem(10,s);
return 0;
}


09-15

09-10 39万+
04-07 1183
10-21 7090
09-28 41万+
02-28 503
12-09 68
04-17 192
12-24 101