《算法》排序

《算法》排序这章的记录,还是看书好啊

从N个输入中找到最大的M个元素所需成本

示例时间空间
排序算法时间 logN l o g N N N
调用初级实现的优先队列 NM N M M M
调用基于堆实现的优先队列 NlogM N l o g M M M

优先队列的各种实现在最坏情况下运行时间的增长数量级

数据结构插入元素删除最大元素
有序数组 N N 1 1
无序数组 1 1 N N
logN l o g N logN l o g N
理想情况 1 1 1 1

各种排序算法的性能特点

算法是否稳定是否为原地排序时间复杂度空间复杂度备注
选择排序 N2 N 2 1 1
插入排序介于 N N N2 N 2 之间 1 1 取决于输入元素的排列情况
希尔排序 NlogN N l o g N ? N6/5 N 6 / 5 1 1
快速排序 NlogN N l o g N lgN l g N 运行效率由概率提供保证
三向快速排序介于 N N NlogN N l o g N 之间 lgN l g N 运行效率由概率保证,同时也取决于输入元素的分布情况
归并排序 NlogN N l o g N N N
堆排序 NlogN N l o g N 1 1

一些问题:

  • 快速排序为什么快?

快速排序之所以最快是因为它的内循环中的指令很少(而且它还能利用缓存,因为它总是顺序地访问数据),它的运行时间的增长数量级为

 cNlgN   c N l g N ,而这里的c比其他线性对数级别的排序算法的应用常数都要小。

附:(部分代码)

选择排序

package cn.net.pikachu.sort;

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

插入排序

package cn.net.pikachu.sort;

public class Insertion {
    public static void sort(Comparable[] a){
    int N = a.length;
    for(int i = 1;i<N;i++){
        for(int j= i;j>0; && less(a[j],a[j-1];j--){
            exch(a,j,j-1);
        }
        }
    }
}

希尔排序

package cn.net.pikachu.sort;

public class Shell{
    public static void sort(Comparable[] a){
    int N = a.length;
    int h = 1;
    while(h<N/3){
        h = 3*h+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,j,j-h);
        }
        }
        h/=3;
    }
    }
}

归并排序

package cn.net.pikachu.sort;

class Merge{
    private static Comparable[] aux;
    public static void sort(Comparable[] a){
    aux = new Comparable[a.length];
    sort(a,0,a.length-1);
    }
    private static void sort(Comparable[] a, int lo, int hi){
    if(hi<=lo){
        return ;
    }
    int mid = lo + (hi-lo)/2;
    sort(a,lo,mid);
    sort(a,mid+1,hi);
    merge(a,lo,mid,hi);
    }
}

快速排序

package cn.net.pikachu.sort;

public class Quick{
    public static void sort(Comparable[] a){
    sort(a,0,a.length-1);
    }
    private static void sort(Comparable[] a, int lo, int hi){
    if(hi<=lo){
        return;
    }
    int j = partition(a,lo,hi);
    sort(a,lo,j-1);
    sort(a,j+1,hi);
    }
    private static int partition(Comparable[] a, int lo, int hi){
    int i = lo;
    int j = hi + 1;
    Comparable v = a[lo];
    while(true){
        while(less(a[++i],v)){
        if(i==hi){
            break;
        }
        }
        while(less[v,a[--j])){
        if(j==lo){
            break;
        }
        }
        if(i>=j){
        break;
        }
        exch(a,i,j);
    }
    exch(a,lo,j);
    return j;
    }
}

优先队列

package cn.net.pikachu.sort;

public class MaxPQ<Key extends Comparable<Key>> {
    private Key[] pq;
    private int N = 0;

    MaxPQ() {
    }

    MaxPQ(int maxN) {
        pq = (Key[]) new Comparable[maxN + 1];
    }

    MaxPQ(Key[] a) {
    }

    void insert(Key v) {
    pq[++N]=v;
    swim(N);
    }

    Key max() {
    }

    Key delMax() {
    Key max = pq[1];
    exch(1,N--1);
    pq[N+1]=null;
    sink(1);
    return max;
    }

    boolean isEmpty() {
        return N == 0;
    }

    int size() {
    return N;
    }
    private boolean less(int i, int j){
    return pq[i].compareTo(pq[j])<0;
    }
    private void exch(int i, int j){
    Key t = pq[i];
    pq[i] = pq[j];
    pq[j]=t;
    }
    private void swim(int k){
    while(k>1 && less(k/2,k)){
        exch(k/2,k);
        k = k/2;
    }
    }
    private void sink(int k){
    while(2*k <= N){
        int j = 2*k;
        if(j<N && less(j,j+1)){
        j++;
        }
        if(!less(k,j)){
        break;
        }
        exch(k,j);
        k = j;
    }
    }
}
点赞