数据结构与算法分析7.1 各种排序算法及其性能比较

写了几种常用的排序算法,并测试比较它们在不同N时花费的时间。

50000以下的整数,一些结果如下:

可见 在N为10和200的时候插入排序比较好;

4000和10000的时候希尔排序不错,10000的时候归并排序最好,但是它需要不断的拷贝;

10000以上快排有很好的效果。

root@ubuntu:sorts# ./a.out 
Input your N:10
Input your times for every sort:3
======================================================
N:10, times:3
q_sort       5(0.00 sec) 2(0.00 sec) 2(0.00 sec) Average:3.00(0.00 sec)
merge_sort   5(0.00 sec) 3(0.00 sec) 3(0.00 sec) Average:3.67(0.00 sec)
insert_sort  2(0.00 sec) 2(0.00 sec) 1(0.00 sec) Average:1.67(0.00 sec)
bubble_sort  2(0.00 sec) 2(0.00 sec) 2(0.00 sec) Average:2.00(0.00 sec)
shell_sort   3(0.00 sec) 2(0.00 sec) 2(0.00 sec) Average:2.33(0.00 sec)
root@ubuntu:sorts# ./a.out 
Input your N:200
Input your times for every sort:3
======================================================
N:200, times:3
q_sort       123(0.00 sec) 40(0.00 sec) 33(0.00 sec) Average:65.33(0.00 sec)
merge_sort   97(0.00 sec) 69(0.00 sec) 66(0.00 sec) Average:77.33(0.00 sec)
insert_sort  124(0.00 sec) 125(0.00 sec) 127(0.00 sec) Average:125.33(0.00 sec)
bubble_sort  561(0.00 sec) 440(0.00 sec) 395(0.00 sec) Average:465.33(0.00 sec)
shell_sort   107(0.00 sec) 45(0.00 sec) 38(0.00 sec) Average:63.33(0.00 sec)
root@ubuntu:sorts# ./a.out 
Input your N:4000
Input your times for every sort:3
======================================================
N:4000, times:3
q_sort       1392(0.00 sec) 4582(0.00 sec) 1143(0.00 sec) Average:2372.33(0.00 sec)
merge_sort   1753(0.00 sec) 1464(0.00 sec) 1497(0.00 sec) Average:1571.33(0.00 sec)
insert_sort  30011(0.03 sec) 21558(0.02 sec) 20967(0.02 sec) Average:24178.67(0.02 sec)
bubble_sort  68045(0.07 sec) 68638(0.07 sec) 69282(0.07 sec) Average:68655.00(0.07 sec)
shell_sort   1202(0.00 sec) 1154(0.00 sec) 1136(0.00 sec) Average:1164.00(0.00 sec)
root@ubuntu:sorts# ./a.out 
Input your N:10000
Input your times for every sort:3
======================================================
N:10000, times:3
q_sort       5570(0.01 sec) 3338(0.00 sec) 3031(0.00 sec) Average:3979.67(0.00 sec)
merge_sort   2770(0.00 sec) 3847(0.00 sec) 2726(0.00 sec) Average:3114.33(0.00 sec)
insert_sort  132152(0.13 sec) 137268(0.14 sec) 130461(0.13 sec) Average:133293.67(0.13 sec)
bubble_sort  532980(0.53 sec) 541508(0.54 sec) 532720(0.53 sec) Average:535736.00(0.54 sec)
shell_sort   4003(0.00 sec) 3989(0.00 sec) 4004(0.00 sec) Average:3998.67(0.00 sec)
root@ubuntu:sorts# ./a.out 
Input your N:200000
Input your times for every sort:3
======================================================
N:200000, times:3
q_sort       56209(0.06 sec) 49304(0.05 sec) 51153(0.05 sec) Average:52222.00(0.05 sec)
merge_sort   76010(0.08 sec) 70382(0.07 sec) 69384(0.07 sec) Average:71925.33(0.07 sec)
insert_sort  53082750(53.08 sec) 60855177(60.86 sec) 55608651(55.61 sec) Average:56515526.00(56.52 sec)
bubble_sort  251693776(251.69 sec) 247223993(247.22 sec) 247935804(247.94 sec) Average:248951191.00(248.95 sec)
shell_sort   830143(0.83 sec) 823296(0.82 sec) 858193(0.86 sec) Average:837210.67(0.84 sec)
root@ubuntu:sorts# vi sorts.c 

root@ubuntu:sorts# 

 

=====================以下是代码============================

#include "stdio.h"
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <string.h>
#include <sys/times.h>
#include <unistd.h>

int bubble_sort(unsigned int * array, int a_len);
int insert_sort(unsigned int * array, int a_len);
typedef int (*sort_funs_t)(unsigned int *array, int a_len);

/*************************start of q sort **********************/
#define Cutoff (10)
static inline void Swap(unsigned int * a1, unsigned int * a2)
{
    unsigned int tmp;
    tmp = *a1;
    *a1 = *a2;
    *a2 = tmp;
}

//找到中间值,并把最小的放在start, 最大的放在end, 中间值放在end - 1位置处,返回中间值的大小
static inline unsigned int find_mid(unsigned int * array, int start, int end)
{
    int mid = (start + end) / 2;
    if (array[start] > array[mid]) {
        Swap(&array[start], &array[mid]);
    }

    if (array[start] > array[end]) {
        Swap(&array[start], &array[end]);
    }

    if ( array[mid] > array[end] ) {
        Swap(&array[mid], &array[end]);
    }

    Swap(&array[mid], &array[end-1]);

    return array[end-1];
}

int my_qsort(unsigned int * array, int start, int end)
{
    int i, j;
    if (start + Cutoff <= end) {//很多数的时候,递归快速排序
        unsigned int mid_value = find_mid(array, start, end);
        i = start, j = end-1;
        for (;;) {
            while (array[ ++i ] < mid_value);
            while (array[ --j ] > mid_value);
            if (i < j) {
                Swap(&array[i], &array[j]);
            } 
            else {
                break;
            }
        }

        //最后记得将暂时放在end-1处的中间值挪到它应当到的位置上去。
        Swap(&array[i], &array[end-1]); 

        my_qsort(array, start, i - 1);
        my_qsort(array, i+1, end);
    }
    else {//这里N <10, 对于少的数,我们用插入排序
         //bubble_sort(array + start, end - start +1);
         insert_sort(array+start, end - start + 1);
    }

    return 0;
}

int q_sort(unsigned int * array, int a_len)
{
    return my_qsort( array, 0, a_len-1); 
}
/*************************end of q sort **********************/

/*************************start of merge sort **********************/
int merge(unsigned int * A, unsigned int * tmp, int start, int mid, int end)
{
    int i = start, j = mid+1;
    int k = start, merge_len = end - start + 1;
    while (i <= mid && j <=end) {
        if (A[i] <= A[j]) {
            tmp[k++] = A[i++]; 
        }
        else {
            tmp[k++] = A[j++];
        } 
    }

    while (i <= mid) {
        tmp[k++] = A[i++];
    }

    while (j <= end) {
        tmp[k++] = A[j++];
    }

    for (i = 0; i < merge_len; i++) {
        A[start+i] = tmp[start+i];
    }
    //memcpy(&A[start], &tmp[start], k*sizeof( unsigned int));
    return k;
}

int Msort(unsigned int * A, unsigned int * tmp, int start, int end)
{
    if (start < end) {
        int mid = (start + end) / 2;
        Msort(A, tmp, start,  mid);
        Msort(A, tmp, mid+1,  end);
        merge(A, tmp, start, mid, end);
    }
}
int merge_sort(unsigned int * A, int a_len)
{
    unsigned int * tmp = malloc( sizeof(unsigned int) * a_len);
    if (tmp) {
        //这里提前分配出算法中需要使用到的内存,免得再算法过程中再次malloc,花费更多时间
        memset(tmp, 0, sizeof(unsigned int) * a_len);
       
        Msort(A, tmp, 0, a_len-1);
    }
    else {
        printf("malloc error!!\n");
        return -1;
    }

    free(tmp);
    return 0;
}
/*************************start of merge sort **********************/

/*************************start of insert sort **********************/
int insert_sort(unsigned int * array, int a_len)
{
    unsigned int tmp = 0;
    int i, j;
    for (i = 1; i < a_len; i++) {
        tmp = array[i];
        for (j = i-1; j >= 0 && (array[j] > tmp); j--) {
            array[j+1] = array[j];
        }
        array[j+1] = tmp; 
    }

    return 0;
}
/*************************start of insert sort **********************/

/*************************start of shell sort **********************/
int shell_sort(unsigned int * array, int a_len)
{
    int shell_i[] = {109,41, 19, 5, 1}; //shell 种子
    int  i, j, k;
    unsigned int tmp;

    int shell_num = sizeof(shell_i) / sizeof(shell_i[0]);
   
    for (i = 0; i < shell_num; i++) {
        for (j = shell_i[i]; j < a_len; j++) {
            tmp = array[j];
            for (k = j-shell_i[i]; k >= 0 && (array[k] > tmp); k -= shell_i[i]) {
                array[k + shell_i[i]] = array[k];
            }
            array[k+shell_i[i]] = tmp;
        }
    }
}
/*************************end of shell sort **********************/


/*************************start of bub sort **********************/
//冒牌排序,没有冒泡的时候说明已经排好序,或者记住交换的点,少排些序
int bubble_sort(unsigned int * array, int a_len)
{
    int i,j, swaped = 1, swap_pos = a_len-1;
    unsigned int tmp = 0;
    for (i = a_len-1; i > 0 && (swaped); i--) {
        swaped = 0;
        for (j = 0; j < i; j++) {
            if (array[j] > array[j+1]) {
                tmp = array[j+1];
                array[j+1] = array[j];
                array[j] = tmp;
                swaped = 1;
                swap_pos = j + 1; 
            } 
        }

        i = swap_pos;
    }
}
/*************************end of bub sort **********************/


void print_array(unsigned int * array, int a_len)
{
    size_t i;
    printf("========================\n");
    for (i = 0; i < a_len; i++ ) {
        printf(" %u", array[i]);
    }
    printf("\n########################\n");
} 
unsigned int choose_issue(unsigned int * array, int a_len, int k, sort_funs_t sort_fun)
{
    //print_array(array, a_len);
    sort_fun(array, a_len);
    //print_array(array, a_len);
    return array[k-1];
}

unsigned int * full_array( int n )
{
    int a_len, i;
    unsigned int * array = NULL;
    a_len = n * sizeof(unsigned int);
    array = malloc(a_len);
    if (array) {
         memset(array, 0, a_len);
         srand(time(NULL));
         for (i = 0; i < n; i++) {
              array[i] = rand() % 50000;
         }
    }
    else {
         assert(0);
    } 

    return array;
}

char func_name[][12] = {
"q_sort",
"merge_sort",
"insert_sort",
"bubble_sort",
"shell_sort",
};


int sorts_test(int N, int times)
{
    clock_t startClock[5][times], stopClock[5][times];
    long cnt = 0, tmp = 0;
    unsigned int *array = NULL;    
    int i, j;

    //这里讲所有排序函数放到这个函数数组中。
    sort_funs_t sort_funs[5];
    sort_funs[0] = q_sort;
    sort_funs[1] = merge_sort;
    sort_funs[2] = insert_sort;
    sort_funs[3] = bubble_sort;
    sort_funs[4] = shell_sort;


    for (i = 0; i < 5; i++) {
        for (j = 0; j < times; j++) {
            if (N >= 50000 && (i == 3 || i == 2)) {
                //too large skip insert_sort and bubble_sort.
                startClock[i][j] = 0; 
                stopClock[i][j] = 0; 
                continue;
            }

            array = full_array( N );
            startClock[i][j] = clock(); 
            choose_issue(array, N, N/2, sort_funs[i]);
            stopClock[i][j] = clock(); 
            if (array) free(array); 
        } 
    }

    printf("======================================================\n");
    printf("N:%d, times:%d\n", N, times);
    for (i = 0; i < 5; i++) {
        printf("%-12s ", func_name[i]);
        cnt = 0;
        for (j = 0; j < times; j++) {
            tmp = (stopClock[i][j] - startClock[i][j]);
            cnt += tmp;
            printf("%ld(%.2f sec)\t", tmp, (double)(tmp)/CLOCKS_PER_SEC);
        }

        printf("\t Average:%.2lf(%.2f sec)\n", (double)cnt/times,
                 (double)cnt/times/CLOCKS_PER_SEC);
    }

}



int main()
{
    int N, times;
    printf("Input your N:");
    scanf("%d", &N);

    while(getchar() != '\n');
    printf("Input your times for every sort:");
    scanf("%d", &times);
    sorts_test(N, times);
}



root@ubuntu:sorts# 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值