• 排序问题1


    本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

     

    排序

    1 排序前提

    1.函数的名称规范

    void X_Sort ( ElementType A[], int N )



    2.大多数情况下,为简单起见,讨论从小大的整数排序



    3.N是正整数



    4只讨论基于比较的排序( >= < 有定义 )



    5.只讨论内部排序



    6稳定性:任意两个相等的数据,排序前后的相对位置不发生改变



    7.没有一种排序是任何情况下都表现最好的

    1 冒泡排序

    1.1算法思想

    第一趟:比较第一个元素和第二元素,如果第一个元素比第二个元素大,就交换位置,否则就不交换位置;在比较第二元素和第三个元素的大小,如果第二个元素比第三个元素大,交换位置,否则不交换位置;然后接着比较第三个元素和第四个元素…… 直到比较到第N-1个元素和第N个元素。这样一趟下来,可以确定最大的元素在N位置

    第二趟:比较第一个元素和第二元素,如果第一个元素比第二个元素大,就交换位置,否则就不交换位置;在比较第二元素和第三个元素的大小,如果第二个元素比第三个元素大,交换位置,否则不交换位置;然后接着比较第三个元素和第四个元素……,直到比较到N-2 N-1个元素。这样,第二趟下面,第二大的元素可以确定在N-1位置。

    第三趟……

    这样到第N趟,就可以吧数组排序完成。

    1.2 伪代码描述

    /*

    * A method to implement bubble sort.If the bubble sort has no any swap

    * operation at one time,indicating the array has been ordered.So we use a

    * tag to make it effective

    *@param a A integer array need to sort

    *@param n The length of the array

    */

    voidbubble_sort(elementType a[], int n) {

    int i, j, flag;

    for (i = n - 1; i >= 0; i--) {

    flag = 0;

    for (j = 0; j < i; j++) {

    if (a[j] > a[j + 1]) {

    swap(&a[j], &a[j + 1]);

    flag = 1;

    }

    }

    if (flag == 0) {

    break;

    }

    }

    }



    1.3 算法分析

    最好的情况:如果这个数组本身就是有序的,那么时间复杂:T=O(N)

    最坏的情况:如果这个数组本身就是逆序的,那么时间复杂度为T=O(N^2)

    因为只有当前面的元素严格的大于后面元素时,才会交换位置,相对位置不会发生改变,那么该算法是稳定的。



    2 选择排序

    2.1算法思想

    选择排序的前提是保证数组中已有元素是有序的。例如在给数组的第i个元素排序(找合适位置)时,已经保证前面i-1个元素是有序的。

    第一趟:当给数组中第一个元素排序时,因为就一个元素,默认就是有序的。

    第二趟:当给数组中第二元素排序时,比较(前一个元素)第一个元素是否比他大,如果大,把前一个元素往后面摞一位,然后。

    第三趟:给数组中第三个元素排序时,比较前一个元素是不是比他大,比他大,前一个元素向后摞一位。在比较在前面一个元素是否比他大,如果比他大,在吧在前一个元素往后摞一位;如果不比他大,那么刚才那个摞的那个空位就就放入该元素。

    第四趟……

    N



    2.2 伪代码描述

    /*

    * Implemet insertion sort.

    *@param a A integer array need to sort

    *@param n The length of the array

    */

    voidinsertion_sort(elementType a[], int n) {

    int i, j;

    elementType temp;

    for (i = 1; i < n; i++) {

    temp = a[i];

    for (j = i; j > 0 && a[j - 1] > temp; j--) {

    a[j] = a[j - 1];

    }

    a[j] = temp;

    }


    }





    2.3 算法分析

    最好的情况:如果这个数组本身就是有序的,那么时间复杂:T=O(N)

    最坏的情况:如果这个数组本身就是逆序的,那么时间复杂度为T=O(N^2)

    因为只有当前面的元素严格的大于后面元素时,才会交换位置,相对位置不会发生改变,那么该算法是稳定的。





    3 时间复杂的下界

    为了说明这个问题,我先给出一个例题:

    给定初始序列{34, 8, 64, 51,32, 21},冒泡排序和插入排序分别需要多少次元素交换才能完成?

    答:冒泡需要9次,选择排序也需要9次。这是一个巧合吗?

    3.1 引入概念

    对于下标i<j,如果A[i]>A[j],则称(i,j)是一对逆序对(inversion)

    问题:序列{34, 8, 64, 51, 32, 21}中有多少逆序对?

    (34, 8) (34, 32) (34, 21) (64, 51) (64, 32) (64, 21) (51, 32) (51, 21) (32, 21)

    有九个逆序对。

    交换两个相邻的逆序对正好消去一个逆序对!

    插入排序(冒泡排序)的时间复杂度可以重新定义为:

    T(N,I)=O(N,I).IN个元素中逆序对的个数

    ——如果需要排序的序列基本有序,则插入排序简单且高效



    3.2 时间复杂度下界

    定理:任意N个不同元素组成的序列平均具有N ( N - 1 ) / 4 个逆序对。

    定理:任何仅以交换相邻两元素来排序的算

    ,其平均时间复杂度为 ( N^2 )

    这意味着:要提高算法效率,我们必须

    1.每次消去不止1个逆序对!

    2. 每次交换相隔较远的2个元素!



    4 希尔排序

    4.1算法思想

    定义增量序列 D M > D M-1 > ... > D 1 = 1

    对每个 D k 进行“D k -间隔”排序 ( k = M, M-1, ... 1 )

    注意:“D k -间隔”有序的序列,在执行“D k-1 -间隔”排序后,仍然是“D k -

    间隔”有序的。下面用一幅图片来说明希尔排序的过程

    4.2希尔排序的伪代码描述

    4.2.1基本的希尔排序的伪代码

    /*

    * Implement base shell sort

    *@param a A integer array need to sort

    *@param n The length of the array

    */

    voidshell_sort_base(elementType a[], int n) {

    int i, j, d;

    elementType temp;

    for (d = n / 2; d > 0; d = d / 2) {

    for (i = d; i < n; i++) {

    temp = a[i];

    for (j = i; j >= d && a[j - d] > temp; j -= d) {

    a[j] = a[j - d];

    }

    a[j] = temp;

    }

    }


    }



    在基本的希尔排序中,我们的间隔取 n/2 n/4 n/8 … n/2^i … 1

    在上面基本的希尔排序中,最坏的时间复杂度T(n)=O(n^2).很糟糕

    下面举一个最坏情况的例子

    4.3 希尔排序的增量序列

    5 堆排序

    5.1 引子

    在介绍堆排序之前,我们先介绍一下选择排序。

    选择排序的算法思想:第一次从N个元素中选择一个最小的。放入0位置,第二次从N个元素中选择第二小的,放入1位置。… 第i次从N个元素选择第i小的元素放入第i-1位置

    下面是选择排序的伪代码描述

    void Selection_Sort ( ElementType A[], int N )

    {

    for ( i = 0; i < N; i ++ ) {

    MinPosition = ScanForMin( A, i, N–1 );

    /* A[i]A[N–1]中找最小元,并将其位置赋给MinPosition */

    Swap( A[i], A[MinPosition] );

    /* 将未排序部分的最小元换到有序部分的最后位置 */

    }

    }

    对于交换元素的操作,是线性。问题在于从N个元素每次找到最i小的元素。选择排序比较暴力,他每次都是从N个元素中选择最小的元素,然后进行交换位置。这样时间时间复杂度T(N)=O(N^2).我们如果改进找到最小元的操作?

    答案是使用我们以前学过的工具,最小堆。

    5.2 堆排序算法1---利用最小堆

    算法思想:把用户给定的数组调整成一个最小堆,每次从堆中弹出一个最小的元素,使用临时数组保存,然后在吧临时数组的元素复制回原数组。

    伪代码描述:

    void Heap_Sort ( ElementType A[], int N )

    {

    BuildHeap(A); /* O(N) */

    for ( i=0; i<N; i++ )

    TmpA[i] = DeleteMin(A); /* O(logN) */

    for ( i=0; i<N; i++ ) /* O(N) */

    A[i] = TmpA[i];

    }

    通过伪代码我们可以看到,此算法的时间复杂的度为T(N)=O(NlogN),但是他需要开辟一个临时的数组O(N)来存放已经排序好的元素。而且还修养话费元素复制的时间。

    5.3 堆排序算法2---利用最大堆

    算法思想:首先吧数组调整成最大堆。把最大堆的第一个元素和最后一个元素调换位置。这样最大的元素就在原数组的最后。然后吧剩下n-1个元素调整成最大堆。重复上面的操作。这样每次选出最大的元素。

    伪代码描述:

    void Heap_Sort ( ElementType A[], int N )

    {

    for ( i=N/2-1; i>=0; i-- )/* BuildHeap */

    PercDown( A, i, N );

    for ( i=N-1; i>0; i-- ) {

    Swap( &A[0], &A[i] ); /* DeleteMax */

    PercDown( A, 0, i );

    }

    }



    5.3 算法分析

    1.定理:堆排序处理N个不同元素的随机排列的平均比较次数是2N logN - O(Nlog logN)

    2.虽然堆排序给出最佳平均时间复杂度,但实际效果不如用Sedgewick增量序列的希尔排序。

    3.堆排序好处是取出前i个最小的数。



    6 归并排序

    6.1有序子列归并

    在介绍归并排序的算法之前,我们先来介绍一下“有序子列的归并”下面通过一张图片来介绍

    下面是给出有序子列归并的源代码

    /*

    * Merge sub-sequence to original array.

    * @param a original <code>elementType</code> array to store the elements

    * @param tmpA temporary <code>elementType</code> array to store the temporary elements

    * @param l The start index of left sub-sequence

    * @param r The start index of left sub-sequence

    * @param rightEnd The end index of left sub-sequence

    */

    voidmerge(elementType a[], elementType tmpA[], int l, int r, int rightEnd) {

    /*

    * lefeEnd is the r-1,the sub-sequence is adjacent

    */

    int leftEnd = r - 1;

    /*

    * tmp is the counter of the <code>tmpA</code>

    * we should let <code>tmpA</code> index corresponding original array

    */

    int tmp = l;

    /*

    * Record the quantity of the all elements

    */

    int numElements = rightEnd - l + 1;

    int i;

    while (l <= leftEnd && r <= rightEnd) {

    if (a[l] <= a[r]) {

    tmpA[tmp++] = a[l++];

    } else {

    tmpA[tmp++] = a[r++];

    }

    }

    while (l <= leftEnd) {

    tmpA[tmp++] = a[l++];

    }

    while (r < rightEnd) {

    tmpA[tmp++] = a[r++];

    }


    /*

    * Put <code>tmpA</code> elements into the original array

    */

    for (i = 0; i < numElements; i++, rightEnd--) {

    a[rightEnd] = tmpA[rightEnd];

    }

    }




    这个代码的时间复杂度在上面已经说过了,为T(N)=O(N)

    6.2 递归算法的递归实现

    这个时间复杂的没有最好,最坏,平均。不论什么样的序列,都是NlogN的时间复杂度。

    6.3 递归算法中的临时数组问题

    在归并排序中,我们使用到一个临时数组,那么这个临时数组在哪里分配比较合理?

    设想一下,如果我们在merge函数中申请,那会怎么样呢。那就会出现,没调用一次merge函数,我们需要申请和释放这样的一个临时数组。这样申请释放的操作如下图所示:

    这样会平凡的对内存进行申请和释放,是很不划算的,而且最后还是要申请一个和N一样大学的数组,那么我们还不如自己在接口函数中把她直接定义好。如下图所示:

    虽然我们在一开始归并过程中只会用到临时数组的一小部分,但是总比每次申请释放来的划算。



    6.4 归并排序的非递归实现

    我们知道递归算法是很消耗系统的堆栈,而且很容易造成内存的溢出。所以我们下面我们使用非递归的方法来实现归并排序。

    非递归算法的思想是一开始对数组两两进行归并,然后对两个元素组成的集合在进行两两归并。最后完成数组的排序。下面使用图片来说明

    6.4.1 非递归归并排序的伪代码描述



    /*

    * Use loop method to implement the merge sort

    * @param a A integer array need to sort

    * @param n The length of the array

    */

    voidmerger_SortLoop(elementType a[], int n) {

    int length;

    elementType *tmpA;

    length = 1;

    tmpA = malloc(n * sizeof(elementType));

    if (tmpA != NULL) {

    while (length < n) {

    /*

    * merge ordered sub-sequence into <code>tmpA</code>

    */

    mergerPass(a, tmpA, n, length);

    length *= 2;

    /*

    * merge ordered sub-sequence from <code>tmpA</code> into <code>a</code>

    */

    mergerPass(tmpA, a, n, length);

    length *= 2;

    }

    free(tmpA);

    } else {

    printf("no enough to apply for temporary array");

    }

    }



    7 各种排序算法在PAT的测试结果

    7.1测试题测试样例

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

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

    • 数据1:只有1个元素;

    • 数据211个不相同的整数,测试基本正确性;

    • 数据3103个随机整数;

    • 数据4104个随机整数;

    • 数据5105个随机整数;

    • 数据6105个顺序整数;

    • 数据7105个逆序整数;

    • 数据8105个基本有序的整数;

    • 数据9105个随机正整数,每个数字不超过1000

    输入格式:

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

    输出格式:

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

    输入样例:

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

    输出样例:

    -20 -17 -5 0 4 8 10 29 43 50 98





    7.2冒泡排序的测试结果

    7.3插入排序测试结果

    7.4 堆排序的测试结果

    7.5希尔排序的测试结果

    但是希尔排序也有通过的例子

    7.6 归并排序递归算法测试结果

    7.7 归并算法非递归算法的测试结果

    7.8 结果分析

    从上面的测试结果来看,堆排序,归并排序都完美通过了测试,而且效率挺高的。

    冒泡排序没有通过测试很正常,因为时间复杂度为O(N^2).

    是我感到诧异的是,插入排序居然通过了测试,虽然挺耗时,但是希尔排序在测试点7105个逆序整数竟然没有通过。我的希尔排序使用Sedgewick序列。不是理论上是O(N^(4/3)),怎么会没有通过呢。但是时间复杂度和冒泡排序相近的插入排序居然通过了。好奇怪。而且插入排序在测试点7105个逆序整数全部是逆序数最坏的时间复杂度为O(N^2),怎么就通过了呢。好奇怪。后来多次对希尔排序进行测试,发现有时候可以通过,有时候没有通过,估计是受机器的影响。感觉希尔排序效率不高,平均的都在5000ms以上

    8各种排序的源代码

     1 /*
     2  * bubbleSort.c
     3  *
     4  *  Created on: 2017年5月18日
     5  *      Author: ygh
     6  */
     7 
     8 #include <stdio.h>
     9 
    10 typedef int elementType;
    11 #define  MAX_LENGTH 100000
    12 
    13 /*
    14  * Swap two integer number value
    15  */
    16 void swap(elementType *a, elementType *b) {
    17     int temp = *b;
    18     *b = *a;
    19     *a = temp;
    20 }
    21 /*
    22  * A method to implement bubble sort.If the bubble sort has no any swap
    23  * operation at one time,indicating the array has been ordered.So we use a
    24  * tag to make it effective
    25  *@param a A integer array need to sort
    26  *@param n The length of the array
    27  */
    28 void bubble_sort(elementType a[], int n) {
    29     int i, j, flag;
    30     for (i = n - 1; i >= 0; i--) {
    31         flag = 0;
    32         for (j = 0; j < i; j++) {
    33             if (a[j] > a[j + 1]) {
    34                 swap(&a[j], &a[j + 1]);
    35                 flag = 1;
    36             }
    37         }
    38         if (flag == 0) {
    39             break;
    40         }
    41     }
    42 }
    43 
    44 /*
    45  * Print the array to console
    46  * @param a A integer array need to sort
    47  * @param n The length of the array
    48  */
    49 void printArray(int a[], int n) {
    50     int i;
    51     for (i = 0; i < n; i++) {
    52         if (i == n - 1) {
    53             printf("%d", a[i]);
    54         } else {
    55             printf("%d ", a[i]);
    56         }
    57     }
    58     printf("
    ");
    59 }
    60 
    61 /*
    62  * Get input data from command
    63  */
    64 void getInputData(elementType *a, int n) {
    65     int i;
    66     elementType x;
    67     for (i = 0; i < n; i++) {
    68         scanf("%d", &x);
    69         a[i] = x;
    70     }
    71 }
    72 
    73 int main() {
    74     int a[MAX_LENGTH];
    75     int n;
    76     scanf("%d", &n);
    77     getInputData(a, n);
    78     bubble_sort(a, n);
    79     printArray(a, n);
    80     return 0;
    81 }
    Bubble_Sort
     1 /*
     2  * insertionSort.c
     3  *
     4  *  Created on: 2017年5月18日
     5  *      Author: ygh
     6  */
     7 
     8 #include <stdio.h>
     9 
    10 #define  MAX_LENGTH 100000
    11 typedef int elementType;
    12 
    13 /*
    14  * Swap two integer number value
    15  */
    16 void swap(elementType *a, elementType *b) {
    17     int temp = *b;
    18     *b = *a;
    19     *a = temp;
    20 }
    21 /*
    22  * Implement insertion sort.
    23  *@param a A integer array need to sort
    24  *@param n The length of the array
    25  */
    26 void insertion_sort(elementType a[], int n) {
    27     int i, j;
    28     elementType temp;
    29     for (i = 1; i < n; i++) {
    30         temp = a[i];
    31         for (j = i; j > 0 && a[j - 1] > temp; j--) {
    32             a[j] = a[j - 1];
    33         }
    34         a[j] = temp;
    35     }
    36 
    37 }
    38 
    39 /*
    40  * Print the array to console
    41  * @param a A integer array need to sort
    42  * @param n The length of the array
    43  */
    44 void printArray(int a[], int n) {
    45     int i;
    46     for (i = 0; i < n; i++) {
    47         if (i == n - 1) {
    48             printf("%d", a[i]);
    49         } else {
    50             printf("%d ", a[i]);
    51         }
    52     }
    53     printf("
    ");
    54 }
    55 
    56 /*
    57  * Get input data from command
    58  */
    59 void getInputData(elementType *a, int n) {
    60     int i;
    61     elementType x;
    62     for (i = 0; i < n; i++) {
    63         scanf("%d", &x);
    64         a[i] = x;
    65     }
    66 }
    67 
    68 int main() {
    69     int a[MAX_LENGTH];
    70     int n;
    71     scanf("%d", &n);
    72     getInputData(a, n);
    73     insertion_sort(a, n);
    74     printArray(a, n);
    75     return 0;
    76 }
    Insertion_Sort
      1 /*
      2  * shellSort.c
      3  *
      4  *  Created on: 2017年5月18日
      5  *      Author: ygh
      6  */
      7 
      8 #include <stdio.h>
      9 #include <math.h>
     10 
     11 #define  MAX_LENGTH 100000
     12 typedef int elementType;
     13 
     14 /*
     15  * Swap two integer number value
     16  */
     17 void swap(elementType *a, elementType *b) {
     18     int temp = *b;
     19     *b = *a;
     20     *a = temp;
     21 }
     22 
     23 int getSedgewickStep(int *step, int n) {
     24     int i, v1, v2, counter = 0;
     25     i = 0;
     26     for (i = 0; i < n; i++) {
     27         v1 = 9 * pow(4, i) - 9 * pow(2, i) + 1;
     28         if (v1 > 0 && v1 < n) {
     29             step[counter++] = v1;
     30         }
     31         v2 = pow(4, i) - 3 * pow(2, i) + 1;
     32         if (v2 > 0 && v2 < n) {
     33             step[counter++] = v2;
     34         }
     35         if (v1 > n && v2 > n) {
     36             break;
     37         }
     38     }
     39     return counter;
     40 }
     41 
     42 /*
     43  * A method to implement bubble sort.If the bubble sort has no any swap
     44  * operation at one time,indicating the array has been ordered.So we use a
     45  * tag to make it effective
     46  *@param a A integer array need to sort
     47  *@param n The length of the array
     48  */
     49 void bubble_sort(int a[], int n) {
     50     int i, j, flag;
     51     for (i = n - 1; i >= 0; i--) {
     52         flag = 0;
     53         for (j = 0; j < i; j++) {
     54             if (a[j] > a[j + 1]) {
     55                 swap(&a[j], &a[j + 1]);
     56                 flag = 1;
     57             }
     58         }
     59         if (flag == 0) {
     60             break;
     61         }
     62     }
     63 }
     64 
     65 /*
     66  * Implement base shell sort
     67  *@param a A integer array need to sort
     68  *@param n The length of the array
     69  */
     70 void shell_sort_expand_Sedgewick(elementType a[], int n) {
     71     int i, j, d, counter, step;
     72     elementType temp;
     73     int sequence[] = { 1, 5, 19, 41, 109, 209, 505, 929, 2161, 3905, 8929,
     74             16001, 6289, 64769 };
     75     counter = 13;
     76     /*int sequence[n / 2];
     77      counter = getSedgewickStep(sequence, n);
     78      bubble_sort(sequence, counter);*/
     79     /*printArray(sequence, counter);
     80      return;*/
     81     for (d = 0; d < counter && sequence[d] < n; d++) {
     82         step = sequence[d];
     83         for (i = step; i < n; i++) {
     84             temp = a[i];
     85             for (j = i; j >= step && a[j - step] > temp; j -= step) {
     86                 a[j] = a[j - step];
     87             }
     88             a[j] = temp;
     89         }
     90     }
     91 
     92 }
     93 
     94 /*
     95  * Implement base shell sort
     96  *@param a A integer array need to sort
     97  *@param n The length of the array
     98  */
     99 void shell_sort_expand_Sedgewick2(elementType a[], int n) {
    100     int i, j, d, counter, step;
    101     elementType temp;
    102     int sequence[n / 2];
    103     counter = getSedgewickStep(sequence, n);
    104     bubble_sort(sequence, counter);
    105     for (d = 0; d < counter && sequence[d] < n; d++) {
    106         step = sequence[d];
    107         for (i = step; i < n; i++) {
    108             temp = a[i];
    109             for (j = i; j >= step && a[j - step] > temp; j -= step) {
    110                 a[j] = a[j - step];
    111             }
    112             a[j] = temp;
    113         }
    114     }
    115 
    116 }
    117 
    118 /*
    119  * Implement base shell sort
    120  *@param a A integer array need to sort
    121  *@param n The length of the array
    122  */
    123 void shell_sort_base(elementType a[], int n) {
    124     int i, j, d;
    125     elementType temp;
    126     for (d = n / 2; d > 0; d = d / 2) {
    127         for (i = d; i < n; i++) {
    128             temp = a[i];
    129             for (j = i; j >= d && a[j - d] > temp; j -= d) {
    130                 a[j] = a[j - d];
    131             }
    132             a[j] = temp;
    133         }
    134     }
    135 
    136 }
    137 
    138 /*
    139  * Print the array to console
    140  * @param a A integer array need to sort
    141  * @param n The length of the array
    142  */
    143 void printArray(int a[], int n) {
    144     int i;
    145     for (i = 0; i < n; i++) {
    146         if (i == n - 1) {
    147             printf("%d", a[i]);
    148         } else {
    149             printf("%d ", a[i]);
    150         }
    151     }
    152     printf("
    ");
    153 }
    154 
    155 /*
    156  * Get input data from command
    157  */
    158 void getInputData(elementType *a, int n) {
    159     int i;
    160     elementType x;
    161     for (i = 0; i < n; i++) {
    162         scanf("%d", &x);
    163         a[i] = x;
    164     }
    165 }
    166 
    167 int main() {
    168     int a[MAX_LENGTH];
    169     int n;
    170     scanf("%d", &n);
    171     getInputData(a, n);
    172     shell_sort_expand_Sedgewick2(a, n);
    173     printArray(a, n);
    174     return 0;
    175 }
    Shell_Sort
      1 /*
      2  * heapSort.c
      3  *
      4  *  Created on: 2017年5月18日
      5  *      Author: ygh
      6  */
      7 
      8 #include <stdio.h>
      9 
     10 #define  MAX_LENGTH 100000
     11 typedef int elementType;
     12 
     13 /*
     14  * Swap two integer number value
     15  */
     16 void swap(elementType *a, elementType *b) {
     17     int temp = *b;
     18     *b = *a;
     19     *a = temp;
     20 }
     21 
     22 /*
     23  * Update the element of tree make the tree to be a maximal heap
     24  * @param a A <code>elementType</code> array to store the elements
     25  * @param p The index of the element need to update
     26  * @param n The length of the array
     27  */
     28 void percDowm(elementType a[], int p, int n) {
     29     int parent, child;
     30     elementType x;
     31     x = a[p];
     32     for (parent = p; (parent * 2 + 1) < n; parent = child) {
     33         child = parent * 2 + 1;
     34         if ((child != n - 1) && a[child] < a[child + 1]) {
     35             child++;
     36         }
     37         if (x >= a[child]) {
     38             break;
     39         } else {
     40             a[parent] = a[child];
     41         }
     42     }
     43     a[parent] = x;
     44 }
     45 
     46 /*
     47  * Implement heap sort
     48  * @param a A integer array need to sort
     49  * @param n The length of the array
     50  */
     51 void heap_sort(elementType a[], int n) {
     52     int i;
     53     /*
     54      * Build max heap
     55      */
     56     for (i = n / 2 - 1; i >= 0; i--) {
     57         percDowm(a, i, n);
     58     }
     59 
     60     /*
     61      * Swap and update heap
     62      */
     63     for (i = n - 1; i > 0; i--) {
     64         swap(&a[0], &a[i]);
     65         percDowm(a, 0, i);
     66     }
     67 }
     68 
     69 /*
     70  * Print the array to console
     71  * @param a A integer array need to sort
     72  * @param n The length of the array
     73  */
     74 void printArray(int a[], int n) {
     75     int i;
     76     for (i = 0; i < n; i++) {
     77         if (i == n - 1) {
     78             printf("%d", a[i]);
     79         } else {
     80             printf("%d ", a[i]);
     81         }
     82     }
     83     printf("
    ");
     84 }
     85 
     86 /*
     87  * Get input data from command
     88  */
     89 void getInputData(elementType *a, int n) {
     90     int i;
     91     elementType x;
     92     for (i = 0; i < n; i++) {
     93         scanf("%d", &x);
     94         a[i] = x;
     95     }
     96 }
     97 
     98 int main() {
     99     int a[MAX_LENGTH];
    100     int n;
    101     scanf("%d", &n);
    102     getInputData(a, n);
    103     heap_sort(a, n);
    104     printArray(a, n);
    105     return 0;
    106 }
    Heap_Sort
      1 /*
      2  * mergeSort.c
      3  *
      4  *  Created on: 2017年5月18日
      5  *      Author: ygh
      6  */
      7 
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #define  MAX_LENGTH 100000
     11 
     12 typedef int elementType;
     13 
     14 /*
     15  * Swap two integer number value
     16  */
     17 void swap(elementType *a, elementType *b) {
     18     int temp = *b;
     19     *b = *a;
     20     *a = temp;
     21 }
     22 
     23 /*
     24  * Merge sub-sequence to original array.
     25  * @param a original <code>elementType</code> array to store the elements
     26  * @param tmpA temporary  <code>elementType</code> array to store the temporary elements
     27  * @param l The start index of left sub-sequence
     28  * @param r The start index of left sub-sequence
     29  * @param rightEnd The end index of left sub-sequence
     30  */
     31 void merge(elementType a[], elementType tmpA[], int l, int r, int rightEnd) {
     32     /*
     33      * lefeEnd is the r-1,the sub-sequence is adjacent
     34      */
     35     int leftEnd = r - 1;
     36     /*
     37      * tmp is the counter of the <code>tmpA</code>
     38      * we should let <code>tmpA</code> index corresponding original array
     39      */
     40     int tmp = l;
     41     /*
     42      * Record the quantity of the all elements
     43      */
     44     int numElements = rightEnd - l + 1;
     45     int i;
     46     while (l <= leftEnd && r <= rightEnd) {
     47         if (a[l] <= a[r]) {
     48             tmpA[tmp++] = a[l++];
     49         } else {
     50             tmpA[tmp++] = a[r++];
     51         }
     52     }
     53     while (l <= leftEnd) {
     54         tmpA[tmp++] = a[l++];
     55     }
     56     while (r <= rightEnd) {
     57         tmpA[tmp++] = a[r++];
     58     }
     59 
     60     /*
     61      * Put <code>tmpA</code> elements into the original array
     62      */
     63     for (i = 0; i < numElements; i++, rightEnd--) {
     64         a[rightEnd] = tmpA[rightEnd];
     65     }
     66 }
     67 
     68 /*
     69  * Implement the merge sort
     70  * @param a original <code>elementType</code> array to store the elements
     71  * @param tmpA temporary  <code>elementType</code> array to store the temporary elements
     72  * @param l The start index of the array which need to sort
     73  * @param rightEnd The end index of the array which need to sort
     74  */
     75 void mergetSortRecursive(elementType a[], elementType tmpA[], int l,
     76         int rightEnd) {
     77     int center;
     78     if (l < rightEnd) {
     79         center = (l + rightEnd) / 2;
     80         mergetSortRecursive(a, tmpA, l, center);
     81         mergetSortRecursive(a, tmpA, center + 1, rightEnd);
     82         merge(a, tmpA, l, center + 1, rightEnd);
     83     }
     84 }
     85 
     86 /*
     87  * Implement merge sort
     88  * @param a A integer array need to sort
     89  * @param n The length of the array
     90  */
     91 void merger_sortRecursive(elementType a[], int n) {
     92     elementType *tmpA;
     93     tmpA = malloc(n * sizeof(elementType));
     94     if (tmpA != NULL) {
     95         mergetSortRecursive(a, tmpA, 0, n - 1);
     96         free(tmpA);
     97     } else {
     98         printf("no enough space to apply for temporary array");
     99     }
    100 }
    101 
    102 /*
    103  *merge ordered sub-sequence
    104  * @param a original <code>elementType</code> array to store the elements
    105  * @param tmpA temporary  <code>elementType</code> array to store the temporary elements
    106  * @param n The length of the a
    107  * @param the ordered current sub-sequence length
    108  */
    109 void mergerPass(elementType a[], elementType tmpA[], int n, int lenth) {
    110     int i, j;
    111     /*
    112      * The loop will stop when meet the last two ordered sub-sequence
    113      * The rest may be two sub-sequence of one sub-sequence
    114      */
    115     for (i = 0; i <= n - 2 * lenth; i += lenth * 2) {
    116         merge(a, tmpA, i, i + lenth, i + 2 * lenth - 1);
    117     }
    118     /*
    119      *If the rest of is two sub-sequence
    120      */
    121     if (i + lenth < n) {
    122         merge(a, tmpA, i, i + lenth, n - 1);
    123     } else {
    124         for (j = i; j < n; j++)
    125             tmpA[j] = a[j];
    126     }
    127 }
    128 
    129 /*
    130  * Use loop method to implement the merge sort
    131  * @param a A integer array need to sort
    132  * @param n The length of the array
    133  */
    134 void merger_SortLoop(elementType a[], int n) {
    135     int length;
    136     elementType *tmpA;
    137     length = 1;
    138     tmpA = malloc(n * sizeof(elementType));
    139     if (tmpA != NULL) {
    140         while (length < n) {
    141             /*
    142              * merge ordered sub-sequence into <code>tmpA</code>
    143              */
    144             mergerPass(a, tmpA, n, length);
    145             length *= 2;
    146             /*
    147              * merge ordered sub-sequence from <code>tmpA</code> into <code>a</code>
    148              */
    149             mergerPass(tmpA, a, n, length);
    150             length *= 2;
    151         }
    152         free(tmpA);
    153     } else {
    154         printf("no enough to apply for temporary array");
    155     }
    156 }
    157 
    158 /*
    159  * Print the array to console
    160  * @param a A integer array need to sort
    161  * @param n The length of the array
    162  */
    163 void printArray(int a[], int n) {
    164     int i;
    165     for (i = 0; i < n; i++) {
    166         if (i == n - 1) {
    167             printf("%d", a[i]);
    168         } else {
    169             printf("%d ", a[i]);
    170         }
    171     }
    172     printf("
    ");
    173 }
    174 
    175 /*
    176  * Get input data from command
    177  */
    178 void getInputData(elementType *a, int n) {
    179     int i;
    180     elementType x;
    181     for (i = 0; i < n; i++) {
    182         scanf("%d", &x);
    183         a[i] = x;
    184     }
    185 }
    186 
    187 int main() {
    188     int a[MAX_LENGTH];
    189     int n;
    190     scanf("%d", &n);
    191     getInputData(a, n);
    192 //    merger_sortRecursive(a, n);
    193     merger_SortLoop(a, n);
    194     printArray(a, n);
    195     return 0;
    196 }
    Merge_Sort

    辛苦一天,数据结构课程的编程练习总算是进入了前100名。付出是值得的

  • 相关阅读:
    Codeforces Round #326 (Div. 2)
    UVAlive 6611 Alice's Print Service 二分
    codeforces868D Huge Strings
    [HNOI2016]大数
    [NOI 2015]软件包管理器
    幻方
    poj3728 商务旅行
    [SCOI2016]背单词
    [USACO12FEB]牛的IDCow IDs
    [Cqoi2010]扑克牌
  • 原文地址:https://www.cnblogs.com/yghjava/p/6876197.html
Copyright © 2020-2023  润新知