zoukankan      html  css  js  c++  java
  • PTA 5-12 排序 (25分)

    给定NN个(长整型范围内的)整数,要求输出从小到大排序后的结果。

    本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:

    • 数据1:只有1个元素;
    • 数据2:11个不相同的整数,测试基本正确性;
    • 数据3:103个随机整数;
    • 数据4:104个随机整数;
    • 数据5:105个随机整数;
    • 数据6:105个顺序整数;
    • 数据7:105个逆序整数;
    • 数据8:105个基本有序的整数;
    • 数据9:105个随机正整数,每个数字不超过1000。

      输入格式:

      输入第一行给出正整数NN(le 10^5105​​),随后一行给出NN个(长整型范围内的)整数,其间以空格分隔。

      输出格式:

      在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。

      输入样例:

      11
      4 981 10 -17 0 -20 29 50 8 43 -5
      

      输出样例:

      -20 -17 -5 0 4 8 10 29 43 50 981
    • 下面试验了各种排序算法的的表现
    • 算法/时间复杂度

      10^3的随机整数

      10^4个随机整数

      10^5个随机整数

      10^5个顺序整数

      10^5个逆序整数

      10^5个基本有序的整数

      10^5个随机正整数,每个数不超过1000

      冒泡排序

      4ms

      228ms

      >10s

      88ms

      >10s

      650ms

      >10s

      插入排序

      3ms

      35ms

      4784ms

      82ms

      9206ms

      115ms

      4499ms

      选择排序

      5ms

      332ms

      >10s

      >10s

      >10s

      >10s

      >10s

      归并排序(递归版本)

      4ms

      12ms

      131ms

      82ms

      127ms

      83ms

      75ms

      堆排序

      3ms

      10ms

      103ms

      89ms

      102ms

      126ms

      94ms

      希尔排序

      3ms

      25ms

      128ms

      119ms

      125ms

      117ms

      116ms

      归并排序(循环版本)

      3ms

      24ms

      125ms

      78ms

      99ms

      77ms

      93ms

      快速排序(pivot取中位数)

      3ms

      10ms

      122ms

      76ms

      112ms

      76ms

      69ms

    /* 冒泡排序
     * 1.最好情况 已经有序了O(n) 
     * 2.最坏情况 逆序 O(n^2)
     * 3.平均情况 O(n^2)
     */
    void bubble_sort(int a[],int n) {
        for (int i = n - 1; i > 0; i--) {
            int flag = 0;
            for (int j = 0; j < i; j++) {
                if (a[j] > a[j + 1]) {
                    int temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                    flag = 1;
                }
            }
            if (flag == 0)
                break;
        }
    }
    /* 
     * 插入排序(对于基本有序的数组排序有较好的表现)
     * 1.最好情况  有序  O(n)
     * 2.最坏情况  逆序  o(n^2)
     * 3.平均情况 O(n^2)
     */
    void insertion_sort(int a[],int n) {
        int i, j;
        for (i = 1; i < n; i++) {
            int temp = a[i]; /* 当前要插入的数 */
            for (j = i - 1; j >= 0; j--) {
                if (temp >= a[j])
                    break;
                a[j + 1] = a[j];
            }
            a[j + 1] = temp;
        }
    }
    /*
     * 希尔排序(不稳定) 
     * 1.时间复杂度跟取得序列有关系
     * 2.取 n/2,n/2^2,...,1序列时 最坏情况下时间复杂度为O(n^2)
     * 3.sedgewick序列时 最坏: O(n^3/2) 平均:O(n^5/4)
     */
    void shell_sort(int a[],int n) {
        int i, j;
        int sedgewick[] = { 929,505,209,41,19,5,1,0 };
        for (i = 0; sedgewick[i] >= n; i++);
        for(int d=sedgewick[i];d>0;d=sedgewick[++i])
            for (int p = d; p < n; p++) {
                int temp = a[p];
                for (j = p; j >= d&&a[j - d] > temp; j -= d)
                    a[j] = a[j - d];
                a[j] = temp;
            }
    }
    /* 
     * 选择排序(不稳定 应该是最差的排序算法了吧) 
     * 最好 最坏  平均 时间复杂度都是O(n^2) 
     */
    void  selection_sort(int a[],int n) {
        for (int i = 0; i < n-1; i++) {
            int min = i;
            for (int j = i + 1; j < n; j++) {
                if (a[j] < a[min]) {
                    min = j;
                }
            }
            if (min != i) {
                int temp = a[min];
                a[min] = a[i];
                a[i] = temp;
            }
        }
    }
    /* 
     * 归并排序(递归版本) 在外排序中使用较多
     * 1.时间复杂度 最好  最坏 平均 都是O(n*log n).
     * 2.空间复杂度 是 O(n). 
     */
    void merge1(int a[],int temp[],int left,int right,int rightEnd) {
        int l = left;
        int leftEnd = right -1;
        int r = right;
        int index = rightEnd - left + 1;
        int x = left;
        while (l <= leftEnd && r <= rightEnd) {
            if (a[l] <= a[r]) {
                temp[x++] = a[l++];
            }
            else
                temp[x++] = a[r++];
        }
        while (l <= leftEnd)
            temp[x++] = a[l++];
        while (r <= rightEnd)
            temp[x++] = a[r++];
        for (int i=rightEnd; index > 0; index--,i--)
            a[i] = temp[i];
    }
    
    void mSort1(int a[],int temp[],int left,int right) {
        if (left < right) {
            int mid = (left + right) / 2;
            mSort1(a, temp, left, mid);
            mSort1(a, temp, mid + 1, right);
            merge1(a, temp, left, mid + 1, right);
        }
    
    }
    void merge_sort1(int a[],int n) { 
        int* temp = (int*)malloc(sizeof(int)*n);
        if (temp != NULL ) {
            mSort1(a, temp, 0, n-1);
            free(temp);
        }
        else {
            cout << "内存不足" << endl;
        }
    }
    /*
     * 归并排序循环版本
     * 1. 时间复杂度  最好 最坏 平均 都为O(n * log n)
     * 2. 空间复杂度O(n)
    */
    void merge2(int a[], int temp[], int left, int right, int rightEnd) {
        int l = left;
        int leftEnd = right - 1;
        int r = right;
        int index = rightEnd - left + 1;
        int x = left;
        while (l <= leftEnd && r <= rightEnd) {
            if (a[l] <= a[r]) {
                temp[x++] = a[l++];
            }
            else
                temp[x++] = a[r++];
        }
        while (l <= leftEnd)
            temp[x++] = a[l++];
        while (r <= rightEnd)
            temp[x++] = a[r++];
    }
    
    void mergePass(int a[],int temp[],int n,int length) {
        int i;
        for (i = 0; i + 2 * length <= n; i += 2 * length) {
            merge2(a, temp, i, i + length, i + 2 * length - 1);
        }
        if (i + length < n) {
            merge2(a, temp, i, i + length, n - 1);
        }
        else
            for (int j = i; j < n; j++)
                temp[j] = a[j];
    }
    void merge_sort2(int a[],int n) {
        int* temp = (int*)malloc(n * sizeof(int));
        if (temp != NULL) {
            int length = 1;
            while (length < n) {
                mergePass(a, temp, n, length);
                length *= 2;
                mergePass(temp, a, n, length);
                length *= 2;
            }
            free(temp);
        }
        else {
            cout << "内存不足" << endl;
        }
    }
    /*
     * 堆排序(不稳定) 
     * 最好 最坏 平均 时间复杂度 O(n*log n).
     */
    void adjust(int a[],int i, int n) { 
        int parent, child;
        int temp = a[i];
        for (parent = i; parent * 2 < n - 1; parent = child) {
            child = parent * 2 + 1; /* 先指向左孩子 */
            if (child != n - 1 && a[child+1] > a[child]) {
                child++; /* 右孩子较大则指向右孩子 */
            }
            if (temp >= a[child])
                break;
            else
                a[parent] = a[child];
        }
        a[parent] = temp;
    }
    void heap_sort(int a[], int n) {
        for (int i = (n-1) / 2; i >= 0; i--)
            adjust(a,i,n);  /* 构建最大堆 */
        for (int i = n - 1; i > 0; i--) {
            int temp = a[i];
            a[i] = a[0];
            a[0] = temp;
            adjust(a, 0, i);
        }
    }
    /*
     * 快速排序 (不稳定)
     * 1.最坏情况和主元的选取有一定的关系 如果选首位为主元O(n^2) 
     * 2.最好 平均 O(n * log n)  
     * 3.当待排元素较少时  快排效率会急速下降  此时可采用插入排序
     */
    void swap(int *a, int *b) {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    int median3(int a[],int left,int right) {
        int center = (left + right) / 2;
        if (a[left] > a[center]) {
            swap(&a[left], &a[center]);
        }
        if (a[left] > a[right]) {
            swap(&a[left], &a[right]);
        }
        if (a[center] > a[right]) {
            swap(&a[center], &a[right]);
        }
        swap(&a[center], &a[right-1]); /* 将基准放在数组右端 */
        return a[right-1];
    }
    void qSort(int a[],int left,int right) {
        int cutoff = 100;
        int low, high, pivot;
        if (right - left >= cutoff) {
            pivot = median3(a, left, right);
            low = left;
            high = right - 1;
            while (1) {
                while (a[++low] < pivot);
                while (a[--high] > pivot);
                if (low < high)
                    swap(&a[low], &a[high]);
                else
                    break;
            }
            swap(&a[low], &a[right - 1]);
            qSort(a, left, low - 1);
            qSort(a, low + 1, right);
        }
        else
            insertion_sort(a+left,right-left+1);
    }
    
    void quick_sort(int a[],int n) {
        qSort(a,0,n-1);
    }

    算法/时间复杂度

    10^3的随机整数

    10^4个随机整数

    10^5个随机整数

    10^5个顺序整数

    10^5个逆序整数

    10^5个基本有序的整数

    10^5个随机正整数,每个数不超过1000

    冒泡排序

    4ms

    228ms

    >10s

    88ms

    >10s

    650ms

    >10s

    插入排序

    3ms

    35ms

    4784ms

    82ms

    9206ms

    115ms

    4499ms

    选择排序

    5ms

    332ms

    >10s

    >10s

    >10s

    >10s

    >10s

    归并排序(递归版本)

    4ms

    12ms

    131ms

    82ms

    127ms

    83ms

    75ms

    堆排序

    3ms

    10ms

    103ms

    89ms

    102ms

    126ms

    94ms

    希尔排序

    3ms

    25ms

    128ms

    119ms

    125ms

    117ms

    116ms

    归并排序(循环版本)

    3ms

    24ms

    125ms

    78ms

    99ms

    77ms

    93ms

    快速排序(pivot取中位数)

    3ms

    10ms

    122ms

    76ms

    112ms

    76ms

    69ms

    基数排序

     

     

     

     

     

     

     
  • 相关阅读:
    细说 ASP.NET Cache 及其高级用法【转】
    类变量和实例变量的区别是什么?
    【转】细说Cookie
    【转】细说 Form (表单)
    PHP API中,MYSQL与MYSQLI的持久连接区别
    Extending_and_embedding_php翻译
    linux常见面试题及答案
    手机辐射查询
    php5.3 PHP5.4 PHP5.5 新特性/使用PHP5.5要注意的
    sqoop安装遇到的问题
  • 原文地址:https://www.cnblogs.com/minesweeper/p/6145999.html
Copyright © 2011-2022 走看看