这是基本都一样的部分。
void print_arr(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
if (!i) {
printf("%d", arr[i]);
} else {
printf(" %d", arr[i]);
}
}
printf("\n");
}
void sort(int * arr, int start, int end){
if(end < start)
return;
int index = quik_sort(arr, start, end);
sort(arr, start, index-1);
sort(arr,index +1,end);
}
int main() {
//cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
int n = 6;
int max = 10;
int * arr = (int *) malloc(sizeof(int) * n);
srand(time(0));
//cout << time(0) << endl;
for (int i = 0; i < n; i++) {
arr[i] = rand() % max;
}
print_arr(arr, n);
sort(arr, 0, n-1);
print_arr(arr, n);
return 0;
}
先说非随机化算法:
方法1: 从两边向中间,不符合要求就交换。
int quik_sort(int * arr, int start, int end) {
int i = start;
int j = end + 1;
int x = arr[start];
while(true){
//这里是 "++i"
while(arr[++i] < x);//从后向前找到第一个比 基准(x)小的数。 i指向该数
//--j 所以要在前面 j=end+1
while(arr[--j] > x);//从前到后 第一个比 基准(x)大的数。 j指向该数
if(i >= j)
break;
//进行交换操作
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
arr[start] = arr[j];
arr[j] = x;
//print_arr(arr, 6);
//cout << start << " - " << end << " j=" << j << endl;
return j;
}
方法2:
第一次交换:swap(arr,index,end); 是交换最后一个值和最后一个值。(遍历树从start -> end-1),也可以说是让arr[end]暂存基准值,循环结束后在交换过来。
第二次交换:swap(arr,index++,i); 保证较小的值在前面
地三次交换:swap(arr, end, index); 当期循环结束的时候,index指向的中间的某个位置(值的是基准值应该在的位置),此时arr[index] 是大于或等于基准值的,可以和arr[end](基准值进行交换)
这个算法可以从前向后遍历,也可以从后向前遍历。
index指向的数可以理解为一个待与后面比基准(pivot)交换的数(i指向的数始终比pivot小,要交换到前面),可以比pivot小(就是index==i,就和自身交换,index++)或大(不交换,index不变)。
int quik_sort(int * arr, int start, int end) {
int index = start;
int pivot = arr[index];
swap(arr,index,end);
for(int i=start; i<end ; i++){
if(arr[i] < pivot){
swap(arr,index++,i);
}
}
swap(arr, end, index);
return index;
}
方法3:只有一个quick_sort方法,递归调用自身。其实也就是从两边向中间靠拢。
但是这里每次不是进行两个值的交换,而是把一个值赋值给另一个。 (key始终保存着基准值,即空出来一个位置,可以原地排序。)
这个是我认为相对前两种较好的!因为不会太多的交换操作。
void quick_sort(int * arr, int start, int end){
if(end < start)
return;
int i,j,key;
i = start;
j = end;
key = arr[i];
while(i < j){
while (i < j && arr[j] > key)
j--;
if (i < j)
arr[i++] = arr[j];
while (i < j && arr[i] < key)
i++;
if (i < j)
arr[j--] = arr[i];
}
arr[i] = key;
if(start < i-1)
quick_sort(arr, start, i-1);
if(end > i+1)
quick_sort(arr, i+1, end);
}
随机化算法:
随机化的好处就是防止出现最坏的情况。
Java版的,其实很简单,就是取一个随机数。
private static <E> int partition(E[] array, int begin, int end, Comparator<? super E> cmp) {
int index = begin + RND.nextInt(end - begin + 1);
E pivot = array[index];
swap(array, index, end);
for (int i = index = begin; i < end; ++ i) {
if (cmp.compare(array[i], pivot) <= 0) {
swap(array, index++, i);
}
}
swap(array, index, end);
return (index);
}
分享到:
相关推荐
在本次实验中将数据量提到5万的时候,该类算法运行时间仍在几毫秒左右,而上面的3种算法运行时间已经到达十几秒左右,效率相差已经到达万倍。该类算法的运行时间随着数据的增加,运行时间渐近线性的增加。但注意理论...
快速排序的三种写法及随机主元快速排序时间复杂度是nlgn,
采用java语言实现的排序排序,通俗易懂。
C语言编写的泛型快速排序算法,快速排序使用的是泛型编写,通过自己编写比较回调函数来进行调用,模仿一个API底层函数的写法。
php递归与非递归快速排序写法php递归与非递归快速排序写法php递归与非递归快速排序写法php递归与非递归快速排序写法
快速排序的迭代版本源代码,在vs上调试通过。
网上也有很多类似的代码.在这里写一下自己对快速排序的理解. 快速排序() { { 将a[n]分为三个部分 第一个部分 小于或等于A的,a[m]到a
快排
本文为大家分享了JS快速排序的具体代码,供大家参考,具体内容如下 说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 ...
总结了八大排序算法的写法,并且比较了效率,供大家学习借鉴。
Java最常见的面试问题就是冒泡排序,这种排序算法经常考,希望读者能够用到
插入排序递归非递归汇编写法 内含详细注释
直接选择排序、堆排序、冒泡排序、快速排序、直接插入排序、折半插入排序、Shell排序、归并排序、桶式排序、基数排序
上传了一个最近学到的冒泡排序法的优化写法,大家可自行查阅学习
在插入算法中,实际上是增量法,现在我们在寻找位置的时候增加效率,通过二分查找来选择。
/** 插入式排序, 将后组每个元素取出与前组逐一比较,找到位置插入 */ public static void insertSort(int[] ary){ int i,j,t; for(i=1; i; i++){ t=ary[i]; System.out.print(Arrays.toString(ary));//跟踪...
java for循环的几种写法
C#实现所有经典排序算法 每个人的写法都有不同,仅供参考!
2022整理python常用算法大全(各种算法说明写法)
android 中Handler 的几种写法,很简单的demo,大神简单修改下,用的是Handler.Callback,的方法