【C++】排序算法小结

1、计数排序

如果给定上下界,并且区间不大的话,最适用。

比如对于英文字母数组进行排序。

时间复杂度O(n),空间复杂度O(n)

void countSort(int A[], int n, int low, int high)

{

    int size = high-low+1;

    vector<int> count(size, 0);    //count[i] represents low+i appears count[i] times in A

    for(int i = 0; i < n; i ++)

    {

        count[A[i]-low] ++;

    }

    int ind = 0;

    for(int i = 0; i < size; i ++)

    {

        while(count[i])

        {

            A[ind ++] = low+i;

            count[i] --;

        }

    }

}

 

2、冒泡排序(基础版)

最基础的排序算法,相邻元素两两比较并交换。

时间复杂度O(n2),空间复杂度O(1)。稳定排序。

void bubbleSort(int A[], int n)

{

    for(int i = 0; i < n; i ++)

    {

        for(int j = 0; j < n-i-1; j ++)

        {

            if(A[j] > A[j+1])

                swap(A[j], A[j+1]);

        }

    }

}

 

3、冒泡排序(加速版)

如果中间结果已经有序,即一次遍历过程中不存在需要交换的相邻元素,则结束返回。

时间复杂度O(n2),空间复杂度O(1)。稳定排序。

void bubbleSortAc(int A[], int n)

{

    bool exchange;

    for(int i = 0; i < n; i ++)

    {

        exchange = false;

        for(int j = 0; j < n-i-1; j ++)

        {

            if(A[j] > A[j+1])

            {

                exchange = true;

                swap(A[j], A[j+1]);

            }

        }

        if(exchange == false)

            return;

    }

}

 

4、选择排序

遍历过程中选择最大元素,与末尾元素交换。

时间复杂度O(n2),空间复杂度O(1)。不稳定排序。

void selectSort(int A[], int n)

{

    for(int i = n-1; i >= 0; i --)

    {

        int max = A[0];

        int ind = 0;

        for(int j = 1; j <= i; j ++)

        {

            if(A[j] > max)

            {

                max = A[j];

                ind = j;

            }

        }

        if(ind != i)

            swap(A[ind], A[i]);

    }

}

 

5、插入排序

将当前元素插入局部有序的数组中。

时间复杂度O(n2),空间复杂度O(1)。稳定排序。

void insertSort(int A[], int n)

{

    for(int i = 1; i < n; i ++)

    {//insert A[i] into the right place

        int cur = i-1;

        int value = A[i];

        while(cur >= 0 && A[cur] > value)

        {

            A[cur+1] = A[cur];

            cur --;

        }

        A[cur+1] = value;

    }

}

 

6、快速排序

最常用的排序,使用pivot将数组分成大小两段,递归完成排序。

时间复杂度平均O(nlogn),最坏情况(已排序或逆序)O(n2),空间复杂度O(1)。不稳定排序。

int partition(int A[], int low, int high)

{

    int pivot = A[low];

    int vacant = low;

    while(low < high)

    {

        while(high > low && A[high] >= pivot)

            high --;

        //A[high] < pivot

        if(high > low)

        {

            A[vacant] = A[high];

            vacant = high;

        }

        else

            break;



        while(low < high && A[low] <= pivot)

            low ++;

        //A[low] > pivot

        if(low < high)

        {

            A[vacant] = A[low];

            vacant = low;

        }

        else

            break;

    }

    A[low] = pivot;

    return low;

}

void quickSort(int A[], int low, int high)

{

    if(low < high)

    {

        int pos = partition(A, low, high);

        quickSort(A, low, pos-1);

        quickSort(A, pos+1, high);

    }

}

 

7、堆排序

分为建堆与交换两个过程。

通常用于数组中寻找最大/小的k个元素。

时间复杂度O(nlogn),空间复杂度O(1)。不稳定排序。

void siftDown(int A[], int start, int end)

{

    int temp = A[start];

    int i = start;

    int j = 2*i + 1;    //left child

    while(j <= end)

    {

        if(j+1 <= end && A[j]<A[j+1])

            j = j+1;    //choose the bigger

        if(temp >= A[j])

            break;

        else

        {

            A[i] = A[j];

            i = j;

            j = 2*i + 1;

        }

    }

    A[i] = temp;

}

void heapSort(int A[], int n)

{

    //build max heap

    for(int i = (n-2)/2; i >= 0; i --)

        siftDown(A, i, n-1);



    //sort

    for(int i = n-1; i >= 0; i --)

    {

        swap(A[0], A[i]);

        siftDown(A, 0, i-1);    //not include the i_th node

    }

}

 

8、归并排序

分为局部排序与有序归并。

通常用于内存不足,需要与硬盘交互的排序。

时间复杂度O(nlogn),空间复杂度O(n)。稳定排序。

void merge(int A[], int start, int mid, int end)

{

    int size1 = mid-start+1;

    int* L = new int[size1];

    for(int i = 0; i < size1; i ++)

        L[i] = A[start+i];

    int size2 = end-mid;

    int* R = new int[size2];

    for(int i = 0; i < size2; i ++)

        R[i] = A[mid+1+i];

    

    int i = 0;

    int j = 0;

    int ind = start;

    while(i < size1 && j < size2)

    {

        if(L[i] <= R[j])

        {

            A[ind] = L[i];

            ind ++;

            i ++;

        }

        else

        {

            A[ind] = R[j];

            ind ++;

            j ++;

        }

    }

    while(i < size1)

    {

        A[ind] = L[i];

        ind ++;

        i ++;

    }

    while(j < size2)

    {

        A[ind] = R[j];

        ind ++;

        j ++;

    }

}

void mergeSort(int A[], int start, int end)

{

    if(start < end)

    {

        int mid = (start+end)/2;

        mergeSort(A, start, mid);

        mergeSort(A, mid+1, end);

        merge(A, start, mid, end);

    }

}

 

你可能感兴趣的:(排序算法)