八种排序的简单实现

冒泡排序及优化,参考匈牙利冒泡排序舞蹈

//冒泡递归写法
void f0(int a[], int len)
{
    if (len > 1)
    {
        int Loop = 0;
        for (int i = 0; i < len - 1; i++)
        {
            Loop++;
            if (a[i] > a[i + 1])
            {
                swap(a[i], a[i + 1]);
                Loop = 0;
            }
        }
        f0(a, len - 1 - Loop);
    }
}

//循环写法
void f1(int a[], int len)
{
    for (int i = len - 1; i >= 0; i--)
    {
        int Loop = 0;
        for (int j = 0; j < i; j++)
        {
            if (a[j] > a[j + 1])
            {
                swap(a[j], a[j + 1]);
                Loop = 0;
            }
            else
            {
                Loop++;
            }
        }
        i -= Loop;
    }
}

选择排序,每一趟把最大或者最小的元素放到最后

//递归
void f2(int a[], int len)
{
    if (len > 1)
    {
        int max = a[0];
        int index = 0;
        for (int i = 0; i < len; i++)
        {
            if (a[i] > max)
            {
                index = i;
                max = a[i];
            }
        }
        swap(a[index], a[len - 1]);
        f2(a, len - 1);
    }
}
//循环

void f3(int a[], int len)
{
    for (int i = len - 1; i >= 0; i--)
    {
        int max = a[0];
        int index = 0;
        for (int j = 0; j <= i; j++)
        {
            if (a[j] > max)
            {
                index = j;
                max = a[j];
            }
        }
        swap(a[i], a[index]);
    }
}

插入排序,将前面的n个数视为已排好序,然后将第n+1个数插入到前面的正确位置

//递归
void f4(int a[], int sorted, int len)
{
    if (len != sorted + 1)
    {
        for (int i = sorted + 1; i >= 1 && a[i] < a[i - 1]; i--)
        {
            swap(a[i], a[i - 1]);
        }
        f4(a, sorted + 1, len);
    }
}
//循环

void f5(int a[], int len)
{
    for (int i = 1; i < len; i++)
    {
        for (int j = i; j >= 1 && a[j] < a[j - 1]; j--)
        {
            swap(a[j], a[j - 1]);
        }
    }
}

归并排序,将两端已排好序的序列合并,优化见另一篇博文

void f6(int a[], int len)
{
    if (len > 1)
    {
        f6(a, len / 2);
        f6(a + len / 2, len - len / 2);
        
        int b[len];
        int cnt = 0;
        int start1 = 0, end1 = len / 2;
        int start2 = len / 2, end2 = len;
        
        while (start1 < end1 && start2 < end2)
        {
            if (a[start1] < a[start2])
            {
                b[cnt++] = a[start1++];
            }
            else
            {
                b[cnt++] = a[start2++];
            }
        }
        
        while (start1 < end1)
        {
             b[cnt++] = a[start1++];
        }
        
        while (start2 < end2)
        {
            b[cnt++] = a[start2++];
        }
        
        for (int i = 0; i < len; i++)
        {
            a[i] = b[i];
        }
        
    }
}

快速排序,以第1个数为参照,找到其正确位置,且让其前面的数比参照小,后面的数比参照大

//快排
void f7(int a[], int len)
{
    if (len > 1)
    {
        int key = a[0];
        int l = 0, r = len - 1;
        while (l < r)
        {
            while (l < r && a[r] > key)
            {
                r--;
            }
            a[l] = a[r];
            
            while (l < r && a[l] < key)
            {
                l++;
            }
            a[r] = a[l];
        }
        
        a[l] = key;
        f7(a, l);
        f7(a + l + 1, len - 1 - l);
    }
}

堆排序,首先建堆,从最后一个叶子节点开始,往前修正,建堆后最大的元素在堆顶。交换堆顶与最后一个元素,len--,修正堆顶

//修正堆中索引为index的元素
void update_heap(int a[], int index, int len)
{
    while (index * 2 < len)
    {
        int ch = 2 * index;
        
        if (ch + 1 < len && a[ch + 1] > a[ch])
        {
            ch++;
        }
        
        if (a[ch] > a[index])
        {
            swap(a[ch], a[index]);
            index = ch;
        }
        else
        {
            break;
        }
    }
}
//建堆,交换,修正
void f8(int a[], int len)
{
    for (int i = len / 2 - 1; i >= 0; i--)
    {
        update_heap(a, i, len);
    }
    
    for (int i = len - 1; i >= 1; i--)
    {
        swap(a[i], a[0]);
        update_heap(a, 0, i);
    }
}

基数排序:按照个位数依次进队,然后出队放回数组,按照十位数依次进队,然后出队放回数组... 

//基数排序
void f9(int a[], int len)
{
    queue<int> q[10];
    int q0_size = 0;
    int m = 1;

    while (q0_size != len)
    {
        for (int i = 0; i < len; i++)
        {
            int digit = (a[i] / m) % 10;
            q[digit].push(a[i]);
        }
        q0_size = (int)q[0].size();
        int cnt = 0;
        for (int i = 0; i < 10; i++)
        {
            while (!q[i].empty())
            {
                int temp = q[i].front();
                q[i].pop();
                a[cnt++] = temp;
            }
        }
        m *= 10;
    }
}

希尔排序:增量缩小的插入排序

//希尔排序
void f10(int a[], int len)
{
    for (int gap = len / 2; gap > 0; gap /= 2)
    {
        for (int j = gap; j < len; j++)
        {
            for (int i = j; i - gap >= 0 && a[i] < a[i - gap]; i -= gap)
            {
                swap(a[i], a[i - gap]);
            }
        }
    }
}

main函数

int main()
{
    int a[10] = {4, 2, 5, 6, 1, 0, 3, 7, 8, 9};
    f0(a, 10);
    
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", a[i]);
    }
    putchar(10);
    return 0;
}

前三种简单排序:O(n^2),选择排序不稳定,其它稳定

中间三种好的排序:O(nlogn), 归并排序稳定,其它不稳定

最后两种,希尔不稳定,基数稳定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值