1. 程式人生 > >八種排序的簡單實現

八種排序的簡單實現

氣泡排序及優化,參考匈牙利氣泡排序舞蹈

//冒泡遞迴寫法
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), 歸併排序穩定,其它不穩定

最後兩種,希爾不穩定,基數穩定