码迷,mamicode.com
首页 > 编程语言 > 详细

算法二,深入与优化

时间:2015-03-08 22:44:09      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:

  选择:1、外循环i,范围N-1,最后一位必为最小。

      2、对于N大小,需要N次比较。

      3、运行时间和输入的有序无序随机都无关,因为必须遍历

      4 、数据移动是最少。

      5、优化是堆排序

 

// public static void SelectSort(Comparable[] a) {
// int N = a.length;
// int mins;
// for (int i = 0; i < N - 1; i++) {
// mins = i;
// for (int j = i + 1; j < N; j++) {
//
// if (SortUtils.less(a[j], a[mins])) {
// mins = j;
// }
// SortUtils.exch(a, i, mins);
// }
// }
// }

 

 

插入排序 :1、一般是N2/4比较和交换,最坏是N2/2,最好是N-1比较和0次交换

      2、排有序会比随机和逆序数快得多

    3、小数组经常是用插入,会比递归快,例如快排和归并

// public static void insertsort(Comparable [] a ){
// int n = a.length;
//
// for (int i = 1; i < n; i++) {
// for (int j = i; j >0 && SortUtils.less(a[j], a[j-1]); j--) {
// SortUtils.exch(a, j, j-1);
// }
// }

 

希尔: 1、插入的优化

    2、通过h有序数据,避免了如果主键最小的元素正好在数组尽头,那么插入排序效率不高的情况

    3、递增序列 h= 3h+1,测试中效率最高

    4、通过while循环实现h,再通过h>=1的循环来控制分组,由h=h/3来减少分组距离

  

// public static void shellsort(Comparable[] a ){
//
// int n = a.length;
// int h1 = 1 ;
// while (h1<n/3) {
// h1 = 3*h1+1;
//
//
// }
// while (h1>=1) {
// for (int i = h1; i < n; i++) {
//
// for (int j = i+1; j >=h1 && SortUtils.less(a[j],a[j-h1]); j=j-h1) {
// SortUtils.exch(a, j, j-h);
// }
// }
// h1=h1/3;
//
// }
// }

 

归并:

  1、分治思想

   2、对小规模数据 N=15左右,使用插入排序,测试快10%-15%

    3、测试数据是否已经有序,就是a[mid]<a[mid+1]就是有序,跳出merge方法

  4、使用arraycope不讲元素复制到辅助数组。底层jni。并且辅助数组aux不声明在merge中为局部变量,因为会减低效率

5、4个条件判断:左边板用尽(取右半边的元素)、右半边用尽(取左边板的元素)、右半边的当前元素小于左半边的当前元素(取右半边的元素)、右半边的当前元素大于左边的当前元素(取半边)

6、原地归并的循环K,是循环c【】a数组,i=lo,j=mid+1,是aux数组辅助a数组


public static void ms(Comparable[] a) {
Comparable[] aux1 = a.clone();

ms(a, aux1, 0, a.length - 1);
}

private static void ms(Comparable[] a, Comparable[] aux1, int lo, int hi) {
if (lo>=hi+10) {
Insertion.sort(a);
return;
}
int mid = lo + (hi - lo) / 2;
ms(a, aux1, lo, mid);
ms(a, aux1, mid + 1, hi);

if (!SortUtils.less(aux1[mid + 1], aux1[mid])) {
System.arraycopy(aux1, lo, a, lo, hi - lo + 1);
return;
}

m(a, aux1, lo,mid, hi);
}

private static void m(Comparable[] a, Comparable[] aux1, int lo, int mid,
int hi) {

int j = mid +1;
int i = lo;

for (int k = lo; k < hi; k++) {
if (i>mid) {
a[k]=aux1[j++];
}else if (j>hi) {
a[k]=aux1[i++];
}else if (SortUtils.less(aux1[j], aux1[i])) {
a[k]=aux1[j++];
}else {
a[k]=aux1[i++];
}
}
}

 

 快排:

1、选择基准:在待排序列中,按照某种方式挑出一个元素,作为 "基准"

2、分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大

3、递归地对两个序列进行快速排序,直到序列为空或者只有一个元素。

4、三次取中+插排+聚合相等元素+尾递归 +(多核心多线程)  stl sort 两者效率差不多

 

private static int partition(Comparable[] a, int lo, int hi) {

int i = lo;
int j = hi + 1;
Comparable v = a[lo];

while (true) {
while (SortUtils.less(a[++i], v)) {
if (i == hi)
break;
}
while (SortUtils.less(v, a[--j])) {
if (j == lo)
break;
}
if (i >= j) {
break;
}
SortUtils.exch(a, i, j);
}
SortUtils.exch(a, j, lo);

return j;
}

public static void QuickSort(Comparable[] a, int lo, int hi) {

if (hi <= lo + 10) {
Insertion.sort(a);
return;
}
int k = partition(a, lo, hi);
QuickSort(a, lo, k - 1);
QuickSort(a, k + 1, hi);

}

 

堆排序:

  1、10亿中取10个最大

2、从a【1】使用,跳去a【0】,在exch和less中,减一

3、for循环中sink构造有序堆,while循环中,sink用来排序

4、sink中的while,2j<=h,先是两子节点比较,右边一定小于左边,像一个退役的老人,跟新晋比较,一步一步下滑,swim则是上浮

5、而不使用swim是因为效率

6、先下沉后上浮。字符串或者其他兼职较长进行排序

7、无法利用缓存

8、是我们所知的唯一能够同时最有地利用空间和时间的方法。最坏也是 2NlgN的比较

 

// public static void hs(Comparable[] a) {
// int N = a.length;
// for (int i = N / 2; i > 0; i++) {
// sink1(a, i, N);
// }
// while (N > 1) {
// exch(a, 1, N--);
// sink(a, 1, N);
// }
// }
//
// private static void sink1(Comparable[] a, int i, int n) {
// while(2*i<n){
// int h = 2*i;
// if (h<n && less(a, h, h+1)) {
// h++;
// }if (!less(a,i,h)) {
// break;
// }
// exch(a,i,h);
// i=h;
// }
// }

算法二,深入与优化

标签:

原文地址:http://www.cnblogs.com/ykong/p/4322314.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!