几种常见排序算法总结

常见排序算法总结:

  • 插入排序

  • 选择排序

  • 快速排序

  • 堆排序

  • 希尔排序

  • 归并排序

排序算法衡量标准:

  1. 稳定性

  2. 时间、空间复杂度

一、插入排序(insertion sort)

实际运行时间,更多地取决于输入序列所含逆序对的总数

template <typename T> void List <T>:: insertionSort( Posi(T) p, int n){ 
    for(int r=0;r<n;r++){ 
         insertAfter(search(p->data,r,p),p->data);//查找+插入 
         p=p->succ; remove(p->pred); 
    } 
} 

性能分析:O(n)


二、选择排序(selection sort)

template <typename T> void List <T> ::selectionSort(Posi(T) p, int n){
    Posi(T) head =p->pred; Posi(T) tail =p; //待排序区间(head,tail)
    for(int i=0; i<n; i++) tail=tail->succ; //head/tail可能是头/尾哨兵
    while(1<n){
        //反复从(非平凡的)待排序区间找出最大者,并移至有序区间前段
        insertBefore(tail, remove(selectMax(head->succ,n)));
        tail=tail->red; n- -;//待排序区间、有序区间的范围,均同步更新
    }  
}

性能分析:

当selectMax()复杂度为theta(n)时 ,总体复杂度为theta(n^2) ,尽管如此,元素移动操作远远少于bubble sort,复杂度主要来自于比较操作 ,但是我们可以将selectMax()的复杂度降低为theta(log n)

三、快速排序(Quicksort)

快速排序是一种常用的算法,它利用了分治策略(Divide and Conquer)。虽然它在最坏的情况下可能达到O(n^2)的时间复杂度,但是在平均的情况下,它一般都是非常有效的,所以是一种实用的算法。

算法思路:

选出一个轴点P,令P的左侧元素均小于P点的元素,右侧均大于P点的元素

伪代码:

quickSort(arr[],lo,hi){
    if(lo<hi){
        p=partition(arr,lo,hi);
        quickSort(arr,lo,pi-1);
		quickSort(arr,pi+1,hi);       
    }
}

性能分析:

最坏情况下时间复杂度:O(n^2)

最好情况下时间复杂度:O(n*lg n)

四、堆排序(heap sort)

算法思路:

建堆过程即为排序过程。

堆通常以数组形式表现

Representation Explanation
Arr[(2*i)+1] Returns the left child node
Arr[(2*i)+2] Returns the right child node
Arr[(i-1)/2] Returns the parent node
代码实现:
class Heap{
public:
    inline int left(int idx){
        return (idx<<1)+1;
    }
    inline int right(int idx){
        return (idx<<1)+2;
    }
    void max_heapify(vector<int>& nums, int idx){
        int largest =idx;
        int l =left(idx), r =right(idx);
        if(l<heap_size && nums[l]>nums[largest]) largest=l;
        if(l<heap_size && nums[r]>nums[largest]) largest=r;
        if(largest!=idx) {
            swap(nums[idx],nums[largest]);
            max_heapify(nums,largest);
        }
    }
    void build_max_heap(vector<int> & nums){
        heap_size=nums.size();
        for(int i=(heap_size>>1)-1;i>=0;i--)
            max_heapify(nums,i);
    }
private:
    int heap_size;
}

性能分析:排序时间复杂度为O(n*lg n)


五、希尔排序(shell sort)

将整个序列看作一个矩阵,逐列w-sorting

递减增量 diminishing increment

由粗到细:重排矩阵,使其更窄,再次逐列排序w-ordered

逐步求精:如此往复,直至矩阵变成一列1-sorting

步长序列 step sequence:由各矩阵宽度构成的逆序列

优劣

1.不需要大量的辅助空间,和归并排序一样容易实现

2.希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n^2),而Hibbard增量的希尔排序的时间复杂度为O(n^(3/2)),希尔排序时间复杂度的下界是n*log2n

3.希尔排序没有快速排序算法快,因此中等大小规模表现良好,对规模非常大的数据排序不是最优选择

希尔算法在最坏情况下和平均情况下执行效率相差不是很多,而快速排序在最坏情况下的执行效率会非常差。

void shellsort(int v[],int n)
{
    int gap,i,j,temp;
    for (gap = n/2; gap > 0; gap /= 2)
    {
        for(i = gap; i < n; i++)       
            for(j = i-gap; j>=0 && v[j]>v[j+gap]; j -= gap)
            {
                temp = v[j];
                v[j] = v[j+gap];
                v[j+gap] = temp;
            }     
    }
}


六、归并排序(merge sort)

归并排序(merge sort)

归并排序利用了分治(divide-and-conquer)的思想。

算法思路如下:

MergeSort(arr[],l,r)
If(r>l):
	1. 找到中点,将数组一分为二:mi=(l+r)/2
	2. 对第一个部分进行归并排序:mergeSort(arr,l,m)
	3. 对第二部分进行归并排序:mergeSort(arr,m+1,r)
	4. 将上面两个排好序的序列融合:merge(arr,l,m,r)

性能分析:

1.是稳定的排序算法

2.时间复杂度theta(n*lg n)







猜你喜欢

转载自blog.csdn.net/weixin_30104533/article/details/80561649