算法总结--排序(快排未写)

 

  算法第四版的简化的笔记!给自己看的

  数据,一个长度为n的无序数组

  api

  exch([]a,i,j) 交换数组i与j位置的元素

  less(i,j) 判断大小:数组元素i<j?true:false

一 选择排序 selection

  i=0;从i~n中选取最小值与i交换位置;i++ ;循环;

特点

  运行时间与输入无关(无论多么乱,或者元素全部一样) 排序时间是一样的。

  数据移动是最少的,每个元素只交换一次。

public static void sort(Comparable[] a) {
        int n = a.length;
        for (int i = 1; i < n; i++) {
            int min = i;
            for (int j = i; j < n; j++) {
                if (less(a[j], a[min])) {
                    min = j;
                }
            }
            exch(a, i, min);
        }
    }
View Code

 

二插入排序 insertion

  将i插入已排序的0~i 中合适的位置,i++;循环 

  插入方法:将i与i-1比较,小于则交换i与i-1;i--;循环;直到插入合适位置

特点

  接近有序的数组比乱序或逆序的要快得多

  适合小规模数组,或大规模数组的局部优化

改进

  插入方法不总是交换位置,直接找到位置,后面元素全部右移

  

/**
     * 将a中lf-rt元素排序 不包括rt位置
     * 
     * @param a
     * @param lf
     * @param rt
     */
    public static void sort(Comparable[] a, int lf, int rt) {
        for (int i = lf + 1; i < rt; i++) {
            for (int j = i; j > lf && less(a[j], a[j - 1]); j--) {
                exch(a, j, j - 1);
            }
        }
    }
View Code

 

三 希尔排序 shell

  类似插入排序,插入排序可视为增量h=1的情况。

  参数:增量h递减至1 (h可选,例子增量约等于n/3)

  将h,2h,3h。。

  h+i,2h+i,3h+i..n

  ...分别按插入排序

  h递减(例子增量为h/=3)

  循环,直至h<=1;

public static void sort(Comparable[] a) {
        int N = a.length;
        // 增量
        int h = 0;
        while (h < N / 3)
            h = h * 3 + 1;
        while (h >= 1) {
            for (int i = h; i < N; i++) {
                for (int j = i; j >= h && less(a[j], a[j - h]); j -= h) {
                    exch(a, i, j);
                }
            }
            h /= 3;
        }
    }
View Code

 

四归并排序 merge

  对于两叠已排序的纸牌,只需依次比较两叠中最顶一张,不断取较小的就行了

  归并分为两种 链表排序适合自下而上

1自上而下

  将n不断二分,类似二叉树,最后一个节点一个元素

  1,1合为2

  2,2合为4

  直至合为n

public static void sort(Comparable[] a) {
        int n = a.length;
        Comparable [] aux = new Comparable[n];
        sort(a, 0, n - 1,aux);
    }

    private static void sort(Comparable[] a, int lf, int rt, Comparable[] aux) {
        if (lf >= rt)
            return;
        if((rt-lf)<=15){
            new Insertion().sort(a,lf,rt+1);
        }
        int mid = lf + (rt - lf) / 2;
        sort(a, lf, mid, aux);
        sort(a, mid + 1, rt, aux);
        if (less(a[mid], a[mid + 1]))
            return;
        else
            merge(a, lf, mid, rt, aux);
    }

    /**
     * 将lf-mid 和 mid+1-rt归并
     * 
     * @param a
     * @param lf
     * @param mid
     * @param rt
     * @param aux 
     */
    private static void merge(Comparable[] a, int lf, int mid, int rt, Comparable[] aux) {
        for (int i = lf; i <= rt; i++) {
            aux[i] = a[i];
        }
        int i = lf;
        int j = mid + 1;
        for (int k = lf; k <= rt; k++) {
            if (i > mid)
                a[k] = aux[j++];
            else if (j > rt)
                a[k] = aux[i++];
            else if (less(aux[i], aux[j]))
                a[k] = a[i++];
            else
                a[k] = a[j++];
        }
    }
View Code

 

2自下而上

  直接将n化为1,类似n叉树

  1,1合为2。。。。直至合为n

原始排序:即将已排序子序列合并,需要一个临时数组拷贝两个子序列,然后排序至原始数组对应位置

改进:1当子序列长度小于某个值时,使用插入排序 ,比如长度为15

   2原始排序需要不断拷贝临时数组,可以再开始就一次性拷贝到辅助数组,直接排序到排序数组?减少复制时间 但不能减少空间

五快速排序 

  待续。。。。

posted on 2015-03-01 20:16  初开  阅读(236)  评论(0编辑  收藏  举报

导航