七种排序算法的比较

共对七种常见排序算法进行比较,包括快排、递归、二路归并、冒泡(简单版)、冒泡(改进版)、插入、选择。

测试结果

测试数据是通过Excel生成的随机数,数值0~100000。

sort method10000100000100000010000000
heap15162964413
quick0161722428
merge0313443466
insert474822SkippedSkipped
bubble
(optimised)
21924402SkippedSkipped
bubble
(naive)
25027930SkippedSkipped
select12712245SkippedSkipped

时间单位(ms),>10min的实验跳过

代码实现

使用代码测试时,请在同文件夹下放置测试数据文档,文档名格式为[“TestData_” + scale + “.txt”],scale表示数据量,文档内,第一行为总数据量,之后为随机数序列。

#include <iostream>
#include <fstream>
#include <ctime>
#include <iomanip>
#include <cmath>

#define MAX 100000000
#define MIN 0
#define MID(a, b, c) ((a > b) ? ((b > c) ? b : ((a > c) ? c : a)) : ((a > c) ? a : ((b > c) ? c : b)))

using namespace std;

void swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

/**
 *  Quicksort
 */
int Partition(int data[], int left, int right)
{
    // int pivot = MID(data[left], data[(left + right) / 2], data[right]);

    // select the middle value of the three number
    if (MID(data[left], data[(left + right) / 2], data[right]) == data[right])
    {
        swap(data[left], data[right]);
    }
    if (MID(data[left], data[(left + right) / 2], data[right]) == data[(left + right) / 2])
    {
        swap(data[left], data[(left + right) / 2]);
    }

    int pivot = data[left];
    int l = left, r = right;
    while (l < r)
    {
        while (data[r] >= pivot && l < r)
        {
            r--;
        }
        data[l] = data[r];
        while (data[l] <= pivot && l < r)
        {
            l++;
        }
        data[r] = data[l];
    }
    data[l] = pivot;

    return l;
}

void qsort(int data[], int left, int right)
{
    if (left < right)
    {
        int l = Partition(data, left, right);

        qsort(data, left, l - 1);
        qsort(data, l + 1, right);
    }
}

void sort_quick(int data[], int size)
{
    qsort(data, 1, size - 1);
}

/**
 *  Insertion Sort
 */
void sort_insert(int data[], int size)
{
    for (int i = 2; i < size; i++)
    {
        if (data[i] < data[i - 1])
        {
            int j = i, temp = data[i];
            for (; temp < data[j - 1]; j--)
            {
                data[j] = data[j - 1];
            }
            data[j] = temp;
        }
    }
}

/**
 *  Bubble sort (naive version)
 */
void sort_bubble_naive(int data[], int size)
{
    for (int i = 1; i < size; i++)
    {
        for (int j = 1; j < size - i; j++)
        {
            if (data[j] > data[j + 1])
            {
                int temp = data[j];
                data[j] = data[j + 1];
                data[j + 1] = temp;
            }
        }
    }
}

/**
 *  Bubble sort(optimised version)
 */
void sort_bubble_optimised(int data[], int size)
{
    bool sorted = 0;
    for (int i = 1; i < size; i++)
    {
        if (sorted == 1)
            break;
        for (int j = 1; j < size - i; j++)
        {
            sorted = 1;
            if (data[j] > data[j + 1])
            {
                int temp = data[j];
                data[j] = data[j + 1];
                data[j + 1] = temp;
                sorted = 0;
            }
        }
    }
}

/**
 *  Select sort
 */
void sort_select(int data[], int size)
{
    for (int i = 1; i < size; i++)
    {
        int min = data[i], index = i, temp;
        for (int j = i; j < size; j++)
        {
            if (data[j] < min)
            {
                min = data[j];
                index = j;
            }
        }
        temp = data[index];
        data[index] = data[i];
        data[i] = temp;
    }
}

/**
 *  Merge Sort
 */
void merge(int *seq1, int *seq2, int len1, int len2)
{
    int *result = new int[len1 + len2];
    int i = 0, j = 0, k = 0;

    while (i < len1 && j < len2)
    {
        if (seq1[i] > seq2[j])
            result[k++] = seq2[j++];
        else
            result[k++] = seq1[i++];
    }

    while (i < len1)
        result[k++] = seq1[i++];
    while (j < len2)
        result[k++] = seq2[j++];
    for (int i = 0; i < len1 + len2; i++)
        seq1[i] = result[i];
    delete[] result;
}

void msort(int *seq1, int *seq2, int len1, int len2)
{
    if (seq1 != seq2)
    {
        msort(seq1, seq1 + len1 / 2, len1 / 2, len1 - len1 / 2);
        msort(seq2, seq2 + len2 / 2, len2 / 2, len2 - len2 / 2);
    }

    merge(seq1, seq2, len1, len2);
}

void sort_merge(int data[], int size)
{
    msort(data + 1, data + (size + 1) / 2, (size - 1) / 2, (size - 1) - (size - 1) / 2);
}

/**
 *  Heap Sort
 */
class CHeap
{
  private:
    const int capacity = MAX;
    int *data = new int[capacity];
    int elemNum;

    void adjust(int node)
    {
        int rc = data[node], i;

        for (i = node * 2 + 1; i < elemNum; i = i * 2 + 1)
        {
            if (i + 1 < elemNum && data[i + 1] < data[i])
                i++;
            if (data[i] > rc)
                break;
            data[(i - 1) / 2] = data[i];
        }
        data[(i - 1) / 2] = rc;
    }

  public:
    CHeap(const int d[], int size)
    {
        for (int i = 0; i < size; i++)
            data[i] = d[i];
        elemNum = size;
        for (int i = (elemNum - 1) / 2; i >= 0; i--)
        {
            adjust(i);
        }
    }
    ~CHeap()
    {
        delete[] data;
    }
    void print()
    {
        printf("\n");
        for (int i = 0; i < elemNum; i++)
        {
            printf("%d\t", data[i]);
            if (i + 2 == pow(2, (int)log2(i + 2)))
                cout << endl;
        }
        printf("\n");
    }
    int size()
    {
        return elemNum;
    }
    int top()
    {
        return data[0];
    }
    void push(const int &elem)
    {
        try
        {
            if (elemNum >= capacity)
                throw "Over capacity!";
            elemNum++;

            data[elemNum - 1] = elem;
            for (int node = elemNum; node > 0;)
            {
                int parent = (node - 1) / 2;
                if (data[node] < data[parent])
                {
                    swap(data[parent], data[node]);
                    node = parent;
                }
            }
        }
        catch (const char aMessage[])
        {
            cout << aMessage << endl;
        }
    }
    int pop()
    {
        int temp;
        try
        {
            if (elemNum <= 0)
                throw "Empty";
            temp = data[0];
            data[0] = data[elemNum - 1];
            elemNum--;
            adjust(0);
        }
        catch (const char aMessage[])
        {
            cout << aMessage << endl;
        }

        return temp;
    }
    void sortedOutput(int *d, int num)
    {
        for (int i = 0; i < num; i++)
        {
            d[i] = pop();
        }
    }
};

void sort_heap(int data[], int size)
{
    CHeap h(data, size);
    h.sortedOutput(data, size);
}

//  Test for recording sort time
clock_t testSort(void (*sortFun)(int *, int), string sort_method, string scale)
{
    int n, No;
    clock_t total = 0;
    clock_t start;

    ifstream fin("TestData_" + scale + ".txt");
    ofstream fout("SortedResult\\Handle_" + scale + "_" + sort_method + ".txt");

    fin >> n;
    //cin >> n;

    int *data = new int[n + 1];

    data[0] = MIN;
    for (int i = 1; i <= n; i++)
    {
        fin >> No;
        //cin >> No;
        data[i] = No;
    }
    fin.close();

    start = clock();
    sortFun(data, n + 1);
    total = (clock() - start);
    for (int i = 0; i < n + 1; i++)
        fout << setw(10) << data[i] << (((i + 1) % 10 == 0) ? "\n" : "");
    fout << "\n\nRun time of sort:  " << total << "(ms)\n\n";

    fout.close();

    delete[] data;
    return total;
}

int main()
{
    ofstream fout("Test\\Sort_Cmp_Test_data.md");

    fout << "| sort method | 10000 | 100000 | 1000000 | 10000000 |" << endl;
    fout << "| :--- | :--- | :--- | :--- | :--- |" << endl;
    fout << "| heap |  "
         << testSort(sort_heap, "heap", "10000") << " |"
         << testSort(sort_heap, "heap", "100000") << " |"
         << testSort(sort_heap, "heap", "1000000") << " |"
         << testSort(sort_heap, "heap", "10000000") << " |"
         << endl;
    fout << "| quick |  "
         << testSort(sort_quick, "quick", "10000") << " |"
         << testSort(sort_quick, "quick", "100000") << " |"
         << testSort(sort_quick, "quick", "1000000") << " |"
         << testSort(sort_quick, "quick", "10000000") << " |"
         << endl;
    fout << "| merge |  "
         << testSort(sort_merge, "merge", "10000") << " |"
         << testSort(sort_merge, "merge", "100000") << " |"
         << testSort(sort_merge, "merge", "1000000") << " |"
         << testSort(sort_merge, "merge", "10000000") << " |"
         << endl;
    fout << "| insert|  "
         << testSort(sort_insert, "insert", "10000") << " |"
         << testSort(sort_insert, "insert", "100000") << " |"
         << testSort(sort_insert, "insert", "1000000") << " |"
         << testSort(sort_insert, "insert", "10000000") << " |"
         << endl;
    fout << "| bubble<br>(optimised) |  "
         << testSort(sort_bubble_optimised, "bubble_optimised", "10000") << " |"
         << testSort(sort_bubble_optimised, "bubble_optimised", "100000") << " |"
         << testSort(sort_bubble_optimised, "bubble_optimised", "1000000") << " |"
         << testSort(sort_bubble_optimised, "bubble_optimised", "10000000") << " |"
         << endl;
    fout << "| bubble<br>(naive) |  "
         << testSort(sort_bubble_naive, "bubble_naive", "10000") << " |"
         << testSort(sort_bubble_naive, "bubble_naive", "100000") << " |"
         << testSort(sort_bubble_naive, "bubble_naive", "1000000") << " |"
         << testSort(sort_bubble_naive, "bubble_naive", "10000000") << " |"
         << endl;
    fout << "| select|  "
         << testSort(sort_select, "select", "10000") << " |"
         << testSort(sort_select, "select", "100000") << " |"
         << testSort(sort_select, "select", "1000000") << " |"
         << testSort(sort_select, "select", "10000000") << " |"
         << endl;

    fout.close();

    return 0;
}

对程序员来说,编程能力固然重要,但是眼光与胸怀也是非常重要的,正如两位前辈所说:

We all want good software, but what does it mean for software to be “good”? Convenient features and reliability are what it means to be technically good, but that is not enough. Good software must also be ethically good: it has to respect the users’ freedom. (“An Introduction to GCC” by Richard M. Stallman)

这道理本来是明白不过的,可是我总想不通。师哥当年说我学武的天资聪明,又是乐此而不疲,可是一来过于着迷,二来少了一副救世济人的胸怀,就算毕身勤修苦练,终究达不到绝顶之境。当时我听了不信,心想学武自管学武,那是拳脚兵刃上的功夫,跟气度识见又有甚么干系?这十多年来,却不由得我不信了。(“射雕英雄传” 周伯通语)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值