常见排序算法(总结)

来源:互联网 发布:sql界面添加字段默认值 编辑:程序博客网 时间:2024/06/10 02:31

常见的排序算法总览

算法名 时间复杂度 空间复杂度 稳定性 冒泡排序 O(N2) O(1) 不稳定 选择排序 O(N2) O(1) 不稳定 插入排序 O(N2) O(1) 稳定 归并排序 O(Nlogn) O(N)可以优化到O(1) 稳定 快速排序 O(Nlogn) O(Lognn) 不稳定 堆排序 O(Nlogn) O(1) 不稳定 希尔排序 O(Nlogn) O(1) 不稳定 计数排序 O(N) O(M) 稳定 基数排序 O(N) O(M) 稳定

其中基数排序和基数排序都是基于桶原理的排序(其他排序方法基于比较的排序), 其空间复杂度O(M) 其中, M为桶的个数。 稳定性指的是在排序过程中相同元素的顺序是否会被改变,比如, 在一个数组中出现两个连续的元素{…, 2(a), 2(b), …},若经过排序后这连个元素的顺序被改变为{…, 2(b), 2(a), …},则该排序算法是不稳定的。

1 冒泡排序:

在[0, n-1]的区间内,第一个数和第二个数比较, 如果前面的数比后面大就交换顺序, 然后第二再和第三比较, 依次比较下去, 那么最大的数就会被放在最后面。然后再对[0, n-2]区间进行相同的操作。冒泡排序的迭代是从后向前的, 数组的后i个元素会被优先排序。

class BubbleSort {public:    int* bubbleSort(int* A, int n) {        for(int i=0;i<n;i++)        {//通过这里的j=n-1-i来实现从[0,n-1]到[0, n-i]的迭            for(int j=0;j<n-1-i;j++)                {                if(A[j]>A[j+1])                {                    swap(A[j],A[j+1]);                }            }        }        return A;    }};

2 选择排序:

在范围[0, n-1]上找到一个最小值, 并把它放在位置0上,然后在[1, n-1]的范围选出最小值放在位置1上,依次进行直到只剩下一个数,排序就完成了。注意选择排序的迭代是向后缩小排序范围的, 也就是前i个元素会优先排序, 着刚好与冒泡排序相反。

class SelectionSort {public:    int* selectionSort(int* A, int n) {        int min_index;        for(int i=0;i<n;i++)        {            min_index = i;            for(int j=i+1;j<n;j++)            {                min_index = A[min_index]>A[j] ? j: min_index;//不断比较直到找到最小值            }            swap(A, i, min_index);        }        return A;    }    void swap(int* A, int m, int n)    {        int temp;        temp = A[m];        A[m]=A[n];        A[n]=temp;    }};

3 插入排序:

首先是位置0上的数和位置1上的数进行比较,如果位置1上的数更小就和位置0上的数进行交换, 接下来就看位置2上的数,和位置1上的数进行比较,如果位置2上的数小就和1上的数进行交换。交换之后位置1上的数再和位置0上的数进行比较,如果还是跟小,就和位置0上的数进行交换。

class InsertionSort {public:    int* insertionSort(int* A, int n) {        int finger;        for(int i=0;i<n;i++){            finger=i;            while(finger>0){                if(A[finger-1]>A[finger]){                    swap(A, finger-1,finger);                }                finger--;            }        }        return A;    }    void swap(int* A, int index1, int index2){        int temp;        temp=A[index1];        A[index1]=A[index2];        A[index2]=temp;    }};

4 归并排序:

让数组中的每一个数单独成为长度为1的有序区间,然后把相邻的长度为1 的有序区间进行合并得到长度为2的有序区间。 然后再把相邻有序区间进行合并,得到最大长度为4的有序区间, 直到让数组里所有的数合并为一个有序区间,排序结束。每个合并的过程可以通过两个indexes 来实现。

//归并排序的递归实现class MergeSort {public:    int* mergeSort(int* A, int n) {        division(A, 0, n-1);        return A;    }    void division(int* A, int left, int right){        if(left==right){            return;        }        int mid = (left+right)/2;        division(A, left, mid);        division(A, mid+1, right);        merge(A, left, mid, right);    }    void merge(int* A, int left, int mid, int right){        vector<int> temp(right-left+1);        int l=left;        int r=mid+1;        int index=0;//how to make it better? more precise?         while(l<=mid && r<=right){            temp[index++]=(A[l]<A[r])? A[l++]:A[r++];        }        while(l<=mid){            temp[index++]=A[l++];        }        while(r<=right){            temp[index++]=A[r++];        }        for(int i=0;i<temp.size();i++){            A[left+i]=temp[i];        }    }};

5 快速排序:

#include<stdlib.h>class QuickSort {public:    int* quickSort(int* A, int n) {        division(A, 0,n-1);        return A;    }    void division(int* A, int left, int right){        if(left<right){            int rd = left+(int)(rand()%(right-left+1));            swap(A, rd, right);            int mid = partition(A, left, right);            division(A, left, mid);            division(A, mid+1, right);        }    }    void swap(int* A, int index1, int index2){        int temp;        temp = A[index1];        A[index1]=A[index2];        A[index2]=temp;    }    int partition(int* A, int left, int right){        int initial = left-1;        int index = left;        while(index <= right){            if(A[index]<=A[right]){                swap(A, ++initial,index);            }            index++;        }        return initial;    }};

6 堆排序:

先把数组建立为一个大小为n的大根堆, 堆顶是整个数组的最大值, 将堆顶元素和堆得最后一个数进行交换,然后把最大值脱离出整个堆结构,放在数组最后的位置。然后对前面n-1大小的堆,从堆顶位置进行大根堆的调整,和上一次步骤相同,分离出最大值。直到只剩下一个数,排序过程结束。

class HeapSort {public:    void swap(int* A, int i, int j){        int temp = A[i];        A[i]=A[j];        A[j]=temp;    }    void maxHeap(int* A, int n, int init, int end){        int parent = init, child = 2*parent+1;        int val=A[parent];        while(child<=end){            if(child<end && A[child]<A[child+1])                child++;            if(val<A[child]){                A[parent]=A[child];                parent=child;                child=2*parent +1;            }            else break;        }        A[parent] = val;    }    int* heapSort(int* A, int n) {        for(int i=n/2-1;i>=0;i--){            maxHeap(A,n,i,n-1);        }        for(int i=n-1;i>0;i--){            swap(A,0,i);            maxHeap(A, n,0,i-1);        }        return A;    }};

7 希尔排序:

改良的排序算法,改变了插入排序的步长。

class ShellSort {public:    void swap(int* A, int i, int j){        int temp=A[i];        A[i]=A[j];        A[j]=temp;    }        int* shellSort(int* A, int n) {        for(int step = n/2;step>0;step = step/2){            int index = 0;            //i=step for the first case            for(int i = step ;i<n;i++){                index = i;                while(index>0){                    if((A[index]<A[index-step]) && (index-step>=0)){                        swap(A,index,index-step);                        index = index - step;                    }                     else{                          break;                     }                }            }        }         return A;        }};

8 计数排序:

先建立排序区间内的桶,然后让排序数组里的数对应进桶,然后从最小桶开始依次倒出,倒出顺序就是排序顺序。

#include<vector>class CountingSort {public:    int* countingSort(int* A, int n) {        int max_ele=0, min_ele=A[0];        for(int i=0;i<n;i++){            if(A[i]>max_ele) max_ele = A[i];            if(A[i]<min_ele) min_ele = A[i];         }        int len = max_ele - min_ele +1;        vector<vector<int>> ans(len);        for(int i=0; i<n;i++){            ans[A[i]-min_ele].push_back(A[i]);        }        int count = 0;        for(int i = 0; i < len; i++){            if(!ans[i].empty()){            for(vector<int>::iterator itr=ans[i].begin();itr !=ans[i].end();++itr){                A[count++] = *itr;            }          }        }        return A;    }};

9 基数排序:

根据个位数入桶,然后依次倒出;再根据十位数入桶,依次倒出,直到排序数组的最高位入桶并倒出后排序结束。

class RadixSort {public:    int* radixSort(int* A, int n) {        for(int i=0;i<=4;i++){            distribute(A, n, i);        }        return A;    }    void distribute(int* A, int n, int count){        queue<int> ans[10];        for(int i=0;i<n;i++){            int num=A[i]/pow(10,count);            ans[num%10].push(A[i]);        }        int index =0;        for(int i=0;i<10;i++){            while(!ans[i].empty()){                A[index]=ans[i].front();                ans[i].pop();                index++;            }        }    }};
原创粉丝点击