一、实验目的:
快速排序是将问题分解,在众多排序中速度较快,但快速排序存在局限性,在有序序列的排序中速度就会减慢,所以对快速排序进行优化,用随机化快排与快排时间进行比较。
二、实验内容:
1.分解是将输入数组A[l..r]划分成两个子数组的过程。选择一个p,使得a被划分成三部分,分别是a[l..p-1],a[p]和a[p+1..r]。并且使得a[l..p-1]中的元素都小于等于(或大于等于)a[p],同时a[p]小于等于(或大于等于)a[p+1..r]中的所有元素。
2.解决是调用递归程序,解决分解中划分生成的两个子序列。
3.合并是递归到最深层,已经不能再划分成更小的子序列了,便开始合并。因为在分解的时候已经比较过大小,每一个父序列分解而来的两个子序列不仅是有序的,而且合并成一个序列之后还是有序的。因为快排可以在输入数组上进行操作,所以合并这一步不需要编写代码。
4.上面版本的快排在选取主元的时候,每次都选取最右边的元素。当序列为有序时,会发现划分出来的两个子序列一个里面没有元素,而另一个则只比原来少一个元素。为了避免这种情况,引入一个随机化量来破坏这种有序状态。
在随机化的快排里面,选取a[left..right]中的随机一个元素作为主元,然后再进行划分,就可以得到一个平衡的划分。
三、程序代码:
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
void display(int array[], int maxlen)
{
int i;
for(i = 0; i < maxlen; i++)
{
printf("%-3d ", array[i]);
}
printf("\n");
return ;
}
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
return ;
}
void quicksort(int array[], int maxlen, int begin, int end)
{
int i, j;
if(begin < end)
{
i = begin + 1;
j = end;
while(i < j)
{
if(array[i] > array[begin])
{
swap(&array[i], &array[j]);
j--;
}
else
{
i++;
}
}
if(array[i] >= array[begin])
{
i--;
}
swap(&array[begin], &array[i]);
quicksort(array, maxlen, begin, i);
quicksort(array, maxlen, j, end);
}
}
int Partition(int *arr, int beg, int end)
{
int j;
int sentinel = arr[end];
int i = beg-1;
for(j=beg; j <= end-1; ++j)
{
if(arr[j] <= sentinel)
{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i+1], &arr[end]);
return i+1;
}
int RandomPartition(int *arr, int beg, int end)
{
int i = beg + rand() % (end-beg+1);
swap(&arr[i], &arr[end]);
return Partition(arr, beg, end);
}
void RandomQuickSort(int *arr, int beg, int end)
{
if(beg < end)
{
int pivot = RandomPartition(arr, beg, end);
RandomQuickSort(arr, beg, pivot-1);
RandomQuickSort(arr, pivot+1, end);
}
}
// 主函数
int main()
{
clock_t start,end;
double duration;
int n,i,array[100000];
printf("请输入快排数组个数:");
scanf("%d",&n);
srand(time(NULL));//定义产生随机数组
for(i=1;i<=n;i++)
{
array[i]=rand()%20000+1;
}
int maxlen=n;
//display(array, maxlen);
start=clock();
quicksort(array, maxlen, 0, maxlen-1); // 快速排序
end=clock();
duration = (double)(end- start) / CLOCKS_PER_SEC;
printf( "快排时间:%f seconds\n", duration );
//display(array, maxlen);
srand(time(0));
for(i=0; i <n; i++)
{
array[i] = rand()%20000+1;
}
start=clock();
RandomQuickSort(array, 0, n-1);
end=clock();
duration = (double)(end- start) / CLOCKS_PER_SEC;
printf( "随机化快排时间:%f seconds\n", duration );
for(i=1;i<=n;i++)
{
array[i]=i;
}
start=clock();
quicksort(array, maxlen, 0, n-1); // 快速排序
end=clock();
duration = (double)(end- start) / CLOCKS_PER_SEC;
printf( "快排有序数组时间:%f seconds\n", duration);
start=clock();
RandomQuickSort(array, 0, n-1);
end=clock();
duration = (double)(end- start) / CLOCKS_PER_SEC;
printf( "随机化快排有序数组时间:%f seconds\n", duration );
return 0;
}
四、演示结果:
五、实验结论:
初始为随机的序列,一般情况下且大量数据的前提下,用随机化算法耗时低于确定性算法。同理,初始数组有序时快速排序耗时最长。