八种排序总结

近来复习排序算法和查找算法,做个总结,巩固一下。


1.直接插入排序: 拓展并维护有序区,直至全部有序

code:

void insertSort(int a[], size_t arrSize)
{
    size_t i, j;
    for(i = 1; i <= arrSize-1; ++i)
    {
        j = i;
        a[0] = a[j+1];
        while(j>0)
        {
            if(a[0]<a[j])
            {
                a[j+1] = a[j];
                --j;
            }
            else break;
        }
        a[j+1] = a[0];
    }
}

复杂度:O(n^2)

稳定性:是

最好情况:O(n)顺序排

最差情况:O(n^2)逆序排


2.希尔排序: 取整数d1<n,将相隔d1的整数放在一组进行直接插入排序;再取d2<d1,重复上述操作;直至di=1,所有数放在一组中排序

code:

void shellSort(int a[], int arrSize)
{
    int d, i, j;
    for (d = (arrSize+1)/2; d >= 1; d = (d+1)/2) //保证以di = 1结束
    {
        for (i = d; i < arrSize; ++i)
        {
            int tmp = a[i];
            for (j = i - d; j >= 0 && (a[j] > tmp); j -= d)
            {
                a[j+d] = a[j];
            }
            a[j+d] = tmp;
        }
        if (d == 1) break;
    }
}

复杂度:O(n^2) 比直接插入排序好些

稳定性:是


3.冒泡排序: 从后往前将相邻两个元素中优先级较高的往前“冒”。

code:

void exchange(int &x, int &y)
{
    int tmp = x;
    x = y;
    y= tmp;
}

void bubbleSort(int a[], size_t arrSize)
{
    for (size_t i = 0; i < arrSize-1; ++i)
    {
        for (size_t j = arrSize-1; j > i; --j)
        {
            if(a[j] < a[j-1])
                exchange(a[j], a[j-1]);
        }
    }
}

复杂度:O(n^2)

稳定性:是

最好情况:O(n)顺序排

最差情况:O(n^2)逆序排

4.快速选择排序: 分治+递归,先选一个基准Pivot,一般是第一个或是最后一个,遍历一趟将元素分为左右两部分,以升序举例,左半部分比Pivot小,右半部分比Pivot大。这样继续对左右两边分治下去,可得有序序列。

code:

void swap(int &x, int &y)
{
    int t = x;
    x = y;
    y = t;
}
int Partitioin(int arr[], int p, int q)//arr[p]~arr[q]
{
    int ele = arr[q];
    int i = p-1;
    for (int j = p; j <= q - 1; ++j)
    {
        if (arr[j] <= ele)
        {
            ++i;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i+1], arr[q]);
    return i+1;
}
void QuickSort(int arr[], int p, int q)//arr[p]~arr[q]
{
    if (p < q)
    {
        int pivot = Partitioin(arr, p, q);
        QuickSort(arr, p, pivot-1);
        QuickSort(arr, pivot+1, q);
    }
}

复杂度:O(nlogn)

稳定性:是

最差情况:O(n^2)数组已经排好序


5.直接选择排序: 每趟遍历未排好序的数,将优先级高的交换到前面来

void selectSort(int a[], size_t arrSize)
{
    size_t i, j;
    for (i = 0; i < arrSize; ++i)
    {
        size_t tmp = i;
        for(j = i+1; j < arrSize; ++j)
        {
            if(a[j] < a[tmp])
                tmp = j;
        }
        if(i != tmp)
        {
            int tval = a[i];
            a[i] = a[tmp];
            a[tmp] = tval;
        }
    }
}

复杂度:O(n^2)

稳定性:是

最好情况:O(n)顺序排

最差情况:O(n^2)逆序排


6.堆排: 构造堆,以最小堆为例,堆顶元素比左右孩子都小。关键是堆的构建和维护。

code:

void sink(int heap[], int heapSize, int p)
{
    int q = p << 1, tmp = heap[p];
    while(q <= heapSize)
    {
        if(q < heapSize && heap[q+1] < heap[q])
            q++;
        if(heap[q] >= tmp)
            break;
        heap[p] = heap[q];
        p = q;
        q = p << 1;
    }
    heap[p] = tmp;
}

void build(int heap[], int heapSize)
{
    int i;
    for (i = heapSize/2; i >= 1; --i)
        sink(heap, heapSize, i);
}

void insert(int heap[], int heapSize, int val)
{
    heap[++heapSize] = val;
    int q = heapSize, p = heapSize >> 1;
    while(p && heap[p] > val)
    {
        heap[q] = heap[p];
        q = p;
        p = q >> 1;
    }
    heap[q] = val;
}

int del(int heap[], int heapSize)
{
    int val = heap[1];
    heap[1] = heap[heapSize--];
    sink(heap, heapSize, 1);
    return val;
}

void heapSort(int heap[], int heapSize, int Sorted[])
{
    int i, SortedSize;
    for (i = 1, SortedSize = heapSize; i <= SortedSize; ++i)
    {
        Sorted[i] = del(heap, heapSize);
        heapSize--;
    }
}

复杂度:O(nlogn)

稳定性:是

最好情况:O(n)顺序排

最差情况:O(nlogn)逆序排


7.归并排序: 将n个元素分成各含n/2个元素的子序列,用合并排序对子序列递归排序,合并已排序的序列。

code:

#define INF 2147483647
int a[] = {2,1,4,5,9,6,7,3,8};

int L[100], R[100];


void merge(int a[], int p, int q, int r) //Merge array between a[p~q] and a[q+1~r]
{
    int n1 = q - p + 1, n2 = r - q, i , j, k;
    for (i = 1; i <= n1; ++i)
        L[i] = a[p+i-1];
    for (i = 1; i <= n2; ++i)
        R[i] = a[q+i];
    L[n1+1] = INF; R[n2+1] = INF;
    for (i= 1, j = 1,k = p; k <= r; ++k)
    {
        if (L[i] <= R[j])
            a[k] = L[i++];//原地,不保留原数组
        else
            a[k] = R[j++];
    }
}

void mergeSort(int a[], int p, int r)
{
    if (p < r)
    {
        int q = (p+r) / 2;
        mergeSort(a, p, q);
        mergeSort(a, q+1, r);
        merge(a, p, q, r);
    }
}

复杂度:O(nlogn)

稳定性:是

最好情况:O(n)顺序排

最差情况:O(nlogn)逆序排


8.基数排序 : 对十进制数来说,每位有10种情况,一次查看一位,按数字位排序。

code:

int base[] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 1000000};

multimap<int, int> m_map;

void handleSort(int a[], int arrSize, int d)
{
    m_map.clear();
    for (int i = 0; i < arrSize; ++i)
    {
        m_map.insert(make_pair(a[i]%base[d+1]/base[d], a[i]));
    }
    int p = 0;
    for (int i = 0; i <= 9; ++i)
    {
        multimap<int, int>::size_type cnt = m_map.count(i);
        multimap<int, int>::iterator itr = m_map.find(i);
        for (multimap<int, int>::size_type ct = 0; ct != cnt; ++ct, ++itr)
                a[p++] = itr->second;
    }
}

void radixSort(int a[], int arrSize, int d)//d represents the digits of a[x]
{
    for (int i = 1; i <= d; ++i)
        handleSort(a, arrSize, i);
}

复杂度:O(n)

稳定性:是








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值