标签


排序算法总结

2014年10月01日

整理edX上Data Structures and Algorithms里所有排序算法.

冒泡排序

1.

归并排序

1.

选择排序(selection sort)

/*selection sort*/
//对列表中起始于位置p的连续n个元素做选择排序,valid(p) && rank(p) + n <= size

tamplate <typename T> void List<T>::selectionSort(Posi(T) p,int n){
    //待排区间(head,tail)
    Posi(T) head = p->pred;
    Posi(T) tail = p;
    for(int i=0; i<n; i++){     //head/tail可能是header/trailer.
        tail = tail->succ;      //(tail到trailer的succ了怎么办? 岂不是null了?)    
        /*改进方法:
        if(tail->succ != NULL){
            tail = tail->succ;
        }
        */
    }

    while(n>1){
        insertBefore(tail,remove( selectMax(head->succ,n) ));//insert要new,remove要delete
        tail = tail->pred;                                   //是通常基本操作的100倍
        n--;                                                 //改进(1):直接修改reference
    }                                                        //改进(2):修改succ/pred
}
/*selectMax*/

template <typename T>
Posi(T) List<T>::selectMax(Posi(T) p, int n){
    Posi(T) max = p;

    for(Posi(T) cur=p;n>1;n--){
        if( !lt((cur = cur->succ)->data,max->data) ) //not less than
            max = cur;                               //painter's algorithm
    }                                                //这里有一个trick, 要用>=,不用>
                                                     //selectMax()中对于多个相等的最大元素,选取其中位置最靠后者
    return max;
}
  1. 分析: (1)复杂度O(n^2) (2)但是元素移动操作远少于起泡排序 (3)O(n^2)来自于元素比较 (4)第10章selectMax()可以在O(logn)而不是O(n)时间内完成

插入排序 (Insertion Sort)

1.将序列看成两部分
(1)sorted + unsorted

2.我的想法, 插入只需要对比O(logn)次,(binary compare?); 但是,在list里没办法call-by-rank

3.实现

/*Insertion Sort*/
//对列表中起始于位置p的连续n个元素做插入排序

template<typename T>
void List<T>::insertSort(Posi(T) p,int n){
    for(int r=0;r<n;r++){       //r是已排序的元素个数
        insertAfter( search(p->data,r,p),p->data );     
        p = p->succ;
        remove(p->pred);        //转向下一节点
    }//O(r+1)
}//仅用O(1)辅助空间,就地算法(in-place algorithm)

4.性能分析
(1)最好情况,几乎完全有序,O(n);最坏情况,O(n^2); 但平均也是O(n^2)
(2)selection所有情况都是O(n^2),没有最好最坏

5.后向分析法(backward analysis)
[0+1+...+(n-1)]/2+1 = O(n^2)

6.逆序对 (inversion)
(1)左大右小,构成inversion
(2)inversion记录在右(小)的那个元素
(3)逆序对数量可能n^2
(4)统计每一个元素所对应的inversion有多少个,累计能得到整个序列所含inversion的数目
(5)p所对应的inversion有多少个,就要经过多少次比较才能抵达最终插入位置
(6)最好情况,逆序对总数0,复杂度O(0+n)
(7)最坏情况,逆序对总数n^2,复杂度O(n^2+n)=O(n^2)