• 8.排序


    8.排序

    8.1排序概述

    排序分为内部排序和外部排序

     

     

    8.2冒泡排序法

    基本思想

    对待排序记录关键字从后往前(逆序)进行多遍扫描,当发现相邻两个关键字的次序与排序要求的规则不符时,就将这两个记录进行交换。这样,关键字较小的记录将逐渐从后面向前面移动,就象气泡在水中向上浮一样,所以该算法也称为气泡排序法。

     

     

    算法实现

     1 #include <stdlib.h>
     2 #include <stdio.h>
     3 #include <conio.h>
     4 
     5 void BubbleSort(int a[], int n)  //冒泡排序
     6 {
     7     int i, j, t;
     8     for (i = 0; i<n - 1; i++)
     9     {
    10         for (j = n - 1; j>i; j--)
    11         {
    12             if (a[j - 1]>a[j])
    13             {
    14                 t = a[j - 1];
    15                 a[j - 1] = a[j];
    16                 a[j] = t;
    17             }
    18         }
    19         printf("第%2d遍:", i + 1);
    20         for (j = 0; j<n; j++)
    21             printf("%d ", a[j]);
    22         printf("
    ");
    23     }
    24 }
    25 void BubbleSort1(int a[], int n) //改进冒泡排序
    26 {
    27     int i, j, t, flag = 0;        //flag用来标记是否发生交换
    28     for (i = 0; i<n - 1; i++)
    29     {
    30         for (j = n - 1; j>i; j--)
    31         {
    32             if (a[j - 1]>a[j])//交换数据 
    33             {
    34                 t = a[j - 1];
    35                 a[j - 1] = a[j];
    36                 a[j] = t;
    37                 flag = 1;
    38             }
    39         }
    40         printf("第%2d遍:", i + 1);
    41         for (j = 0; j<n; j++)
    42             printf("%d ", a[j]);
    43         printf("
    ");
    44         if (flag == 0)    //没发生交换,直接跳出循环
    45             break;
    46         else
    47             flag = 0;
    48     }
    49 }
    50 int main()
    51 {
    52     int i;
    53     int a[6] = {69,65,90,37,92,6};
    54     printf("原数据:");
    55     for (i = 0; i<6; i++)
    56         printf("%d ", a[i]);
    57     printf("
    ");
    58 
    59     BubbleSort(a, 6);
    60     printf("冒泡排序后:
    ");
    61     for (i = 0; i<6; i++)
    62         printf("%d ", a[i]);
    63     printf("
    ");
    64 
    65     getch();
    66     return 0;
    67 }

     

     

     

    附:

    用产生的随机数排序

     1 #include <stdlib.h>
     2 #include <stdio.h>
     3 #include <conio.h>
     4 #include <time.h>
     5 #define ARRAYLEN 6
     6 int CreateData(int arr[], int n, int min, int max) //创建一个随机数组,a保存生成的数据,n为数组元素的数量 
     7 {
     8     int i, j, flag;
     9     srand(time(NULL));
    10     if ((max - min + 1)<n) 
    11         return 0; //最大数与最小数之差小于产生数组的数量,生成数据不成功 
    12     for (i = 0; i<n; i++)
    13     {
    14         do
    15         {
    16             arr[i] = (max - min + 1)*rand() / (RAND_MAX + 1) + min; //生成数不能相同
    17             flag = 0;
    18             for (j = 0; j<i; j++)
    19             {
    20                 if (arr[i] == arr[j]) //相同重新生成
    21                     flag = 1;
    22             }
    23         } while (flag);
    24     }
    25     return 1;
    26 }
    27 
    28 void BubbleSort(int a[], int n)  //冒泡排序
    29 {
    30     int i, j, t;
    31     for (i = 0; i<n - 1; i++)
    32     {
    33         for (j = n - 1; j>i; j--)
    34         {
    35             if (a[j - 1]>a[j])
    36             {
    37                 t = a[j - 1];
    38                 a[j - 1] = a[j];
    39                 a[j] = t;
    40             }
    41         }
    42         printf("第%2d遍:", i + 1);
    43         for (j = 0; j<n; j++)
    44             printf("%d ", a[j]);
    45         printf("
    ");
    46     }
    47 }
    48 void BubbleSort1(int a[], int n) //改进冒泡排序
    49 {
    50     int i, j, t, flag = 0;        //flag用来标记是否发生交换
    51     for (i = 0; i<n - 1; i++)
    52     {
    53         for (j = n - 1; j>i; j--)
    54         {
    55             if (a[j - 1]>a[j])//交换数据 
    56             {
    57                 t = a[j - 1];
    58                 a[j - 1] = a[j];
    59                 a[j] = t;
    60                 flag = 1;
    61             }
    62         }
    63         printf("第%2d遍:", i + 1);
    64         for (j = 0; j<n; j++)
    65             printf("%d ", a[j]);
    66         printf("
    ");
    67         if (flag == 0)    //没发生交换,直接跳出循环
    68             break;
    69         else
    70             flag = 0;
    71     }
    72 }
    73 int main()
    74 {
    75     int i, a[ARRAYLEN];
    76     for (i = 0; i<ARRAYLEN; i++)
    77         a[i] = 0;
    78 
    79     if (!CreateData(a, ARRAYLEN, 1, 100))
    80     {
    81         printf("生成随机数不成功!
    ");
    82         getch();
    83         return 1;
    84     }
    85 
    86     printf("原数据:");
    87     for (i = 0; i<ARRAYLEN; i++)
    88         printf("%d ", a[i]);
    89     printf("
    ");
    90 
    91     BubbleSort1(a, ARRAYLEN);
    92     printf("排序后:");
    93     for (i = 0; i<ARRAYLEN; i++)
    94         printf("%d ", a[i]);
    95     printf("
    ");
    96 
    97     getch();
    98     return 0;
    99 }

     

     

    8.3快速排序法

    基本思想:

    快速排序使用分治策略来把待排序数据序列分为两个子序列,具体步骤为:

    (1)从数列中挑出一个元素,称该元素为“基准”。

    (2)扫描一遍数列,将所有比“基准”小的元素排在基准前面,所有比“基准”大的元素排在基准后面。

    (3)通过递归,将各子序列划分为更小的序列,直到把小于基准值元素的子数列和大于基准值元素的子数列排序。

     

     

    算法实现:

     1 #include <stdio.h>
     2 #include <conio.h>
     3 #define ARRAYLEN 8
     4 int Division(int a[], int left, int right) //分割 
     5 {
     6     int base = a[left];    //基准元素
     7     while (left<right)
     8     {
     9         while (left<right && a[right]>base)
    10             --right;     //从右向左找第一个比基准小的元素
    11         a[left] = a[right];
    12         while (left<right && a[left]<base)
    13             ++left;      //从左向右找第一个比基准大的元素
    14         a[right] = a[left];
    15     }
    16     a[left] = base;
    17     return left;
    18 }
    19 void QuickSort(int a[], int left, int right)
    20 {
    21     int i, j;
    22     if (left<right)
    23     {
    24         i = Division(a, left, right);   //分割
    25         QuickSort(a, left, i - 1);      //将两部分分别排序
    26         QuickSort(a, i + 1, right);
    27     }
    28 }
    29 int main()
    30 {
    31     int i, a[ARRAYLEN] = {69,65,90,37,92,6,28,54};
    32     printf("原数据:");
    33     for (i = 0; i<ARRAYLEN; i++)
    34         printf("%d ", a[i]);
    35     printf("
    ");
    36 
    37     QuickSort(a, 0, ARRAYLEN - 1);
    38     printf("排序后:");
    39     for (i = 0; i<ARRAYLEN; i++)
    40         printf("%d ", a[i]);
    41     printf("
    ");
    42 
    43     getch();
    44     return 0;
    45 }

     

     

    8.4选择排序法

    思想:

         选择排序(Selection Sort)的基本思想:对n个记录进行扫描,选择最小的记录,将其输出,接着在剩下的n-1个记录中扫描,选择最小的记录将其输出,……不断重复这个过程,直到只剩一个记录为止。

     

     

    算法实现:

     1 #include <stdio.h>
     2 #include <conio.h>
     3 #define ARRAYLEN 8
     4 void SelectSort(int a[], int n)
     5 {
     6     int i, j, t, k;
     7     for (i = 0; i<n - 1; i++)
     8     {
     9         k = i;
    10         for (j = i; j<n; j++){
    11             if (a[k]>a[j])
    12                 k = j;
    13         }
    14         t = a[i];
    15         a[i] = a[k];
    16         a[k] = t;
    17     }
    18 }
    19 int main()
    20 {
    21     int i, a[ARRAYLEN] = {69,65,90,37,92,6,28,54};
    22     printf("原数据:");
    23     for (i = 0; i<ARRAYLEN; i++)
    24         printf("%d ", a[i]);
    25     printf("
    ");
    26 
    27     SelectSort(a,ARRAYLEN);
    28     printf("排序后:");
    29     for (i = 0; i<ARRAYLEN; i++)
    30         printf("%d ", a[i]);
    31     printf("
    ");
    32 
    33     getch();
    34     return 0;
    35 }

     

     

    8.5堆排序法

    基本思想:

    堆是一个完全二叉树,树中每个结点对应于原始数据的一个记录,并且每个结点应满足以下条件:非叶结点的数据大于或等于其左、右孩子结点的数据(若是按从大到小的顺序排序,则要求非叶结点的数据小于或等于其左、右孩子结点的数据)。

     

    由堆的定义可看出,其根结点为最大值,堆排序就是利用这一特点进行的。堆排序过程包括两个阶段:

    (1)将无序的数据构成堆(即用无序数据生成满足堆定义的完全二叉树)。

    (2)利用堆排序(即用上一步生成的堆输出有序的数据)。

     

    例:对69、65、90、37、92、6、28、54堆排序

     

     

     

     

    算法实现:

     1 #include <stdio.h>
     2 #include <conio.h>
     3 #define ARRAYLEN 8
     4 void HeapAdjust(int a[], int s, int n)//构成堆
     5 {
     6     int j, t;
     7     while (2 * s <n) //第s个结点有右子树 
     8     {
     9         j = 2 * s ;
    10         if ((j + 1)<n)
    11         {
    12             if (a[j]<a[j + 1])//右左子树小于右子树,则需要比较右子树
    13                 j++; //序号增加1,指向右子树 
    14         }
    15         if (a[s]<a[j])//比较s与j为序号的数据
    16         {
    17             t = a[s];  //交换数据 
    18             a[s] = a[j];
    19             a[j] = t;
    20             s = j;//堆被破坏,需要重新调整
    21         }
    22         else //比较左右孩子均大则堆未破坏,不再需要调整
    23             break;
    24     }
    25 }
    26 void HeapSort(int a[], int n)//堆排序
    27 {
    28     int t, i;
    29     int j;
    30     for (i = n/2-1 ; i >= 0; i--)    //将a[0,n-1]建成大根堆
    31         HeapAdjust(a, i, n);
    32     for (i = n - 1; i>0; i--)
    33     {
    34         t = a[0];//与第i个记录交换
    35         a[0] = a[i];
    36         a[i] = t;
    37         HeapAdjust(a, 0, i);        //将a[0]至a[i]重新调整为堆
    38     }
    39 }
    40 int main()
    41 {
    42     int i, a[ARRAYLEN] = {69,65,90,37,92,6,28,54};
    43     printf("原数据:");
    44     for (i = 0; i<ARRAYLEN; i++)
    45         printf("%d ", a[i]);
    46     printf("
    ");
    47 
    48     HeapSort(a,ARRAYLEN);
    49     printf("排序后:");
    50     for (i = 0; i<ARRAYLEN; i++)
    51         printf("%d ", a[i]);
    52     printf("
    ");
    53 
    54     getch();
    55     return 0;
    56 }

     

     

     

    8.6插入排序法

    基本思想:

    插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后移动,为最新元素提供插入空间。

     

     

    算法实现:

     1 #include <stdio.h>
     2 #include <conio.h>
     3 #define ARRAYLEN 8
     4 void InsertSort(int a[], int n)//直接插入排序 
     5 {
     6     int i, j, t;
     7     for (i = 1; i<n; i++)
     8     {
     9         t = a[i];     //取出一个未排序的数据 
    10         for (j = i - 1; j >= 0 && t<a[j]; --j)     //在排序序列中查找位置 
    11             a[j + 1] = a[j]; //向后移动数据 
    12         a[j + 1] = t; //插入数据到序列 
    13     }
    14 }
    15 int main()
    16 {
    17     int i, a[ARRAYLEN] = {69,65,90,37,92,6,28,54};
    18     printf("原数据:");
    19     for (i = 0; i<ARRAYLEN; i++)
    20         printf("%d ", a[i]);
    21     printf("
    ");
    22 
    23     InsertSort(a,ARRAYLEN);
    24     printf("排序后:");
    25     for (i = 0; i<ARRAYLEN; i++)
    26         printf("%d ", a[i]);
    27     printf("
    ");
    28 
    29     getch();
    30     return 0;
    31 }

     

     

    8.7希尔(shell)排序法

    基本思想:

    希尔排序又称为缩小增量排序,也属于插入排序类的算法,是对直接插入排序的一种改进。      

    基本思想就是:将需要排序的序列划分为若干个较小的序列,对这些序列进行直接插入排序,通过这样的操作可使用需要排序的数列基本有序,最后再使用一次直接插入排序。这样,首先对数量较小的序列进行直接插入排序可提高效率,最后对基本有序的序列进行直拦插入排序,也可提高效率,从而使整个排序过程的效率得到提升。

     

     

    算法实现:

     1 #include <stdio.h>
     2 #include <conio.h>
     3 #define ARRAYLEN 8
     4 void ShellSort(int a[], int n)//希尔排序 
     5 {
     6     int d, i, j, x;
     7     d = n / 2;
     8     while (d >= 1) //循环至增量为1时结束 
     9     {
    10         for (i = d; i<n; i++)
    11         {
    12             x = a[i]; //获取序列中的下一个数据 
    13             j = i - d; //序列中前一个数据的序号 
    14             while (j >= 0 && a[j]>x) //下一个数大于前一个数 
    15             {
    16                 a[j + d] = a[j]; //将后一个数向前移动 
    17                 j = j - d; //修改序号,继续向前比较 
    18             }
    19             a[j + d] = x; //保存数据 
    20         }
    21         d /= 2;  //缩小增量 
    22     }
    23 }
    24 int main()
    25 {
    26     int i, a[ARRAYLEN] = {69,65,90,37,92,6,28,54};
    27     printf("原数据:");
    28     for (i = 0; i<ARRAYLEN; i++)
    29         printf("%d ", a[i]);
    30     printf("
    ");
    31 
    32     ShellSort(a,ARRAYLEN);
    33     printf("排序后:");
    34     for (i = 0; i<ARRAYLEN; i++)
    35         printf("%d ", a[i]);
    36     printf("
    ");
    37 
    38     getch();
    39     return 0;
    40 }

     

     

     

    8.8合并(归并)排序法

    基本思想:

    合并排序(Merge Sort)就是将两个或多个有序表合并成一个有序表。

     

    算法实现:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <conio.h>
     4 #define ARRAYLEN 8
     5 void MergeStep(int a[], int r[], int s, int m, int n) //相邻有序段合并 
     6 {
     7     int i, j, k;
     8     k = s;
     9     i = s;
    10     j = m + 1;
    11     while (i <= m && j <= n) //当两个有序表都未结束时,循环比较 
    12     {
    13         if (a[i] <= a[j]) //当较小的元素复制到R中 
    14             r[k++] = a[i++];
    15         else
    16             r[k++] = a[j++];
    17     }
    18     while (i <= m) //将未合并的部分复制到R中 
    19         r[k++] = a[i++];
    20     while (j <= n)
    21         r[k++] = a[j++]; //将未合并的部分复制到R中 
    22 }
    23 void MergePass(int a[], int r[], int n, int len) //完成一遍合并的函数 
    24 {
    25     int s, e;
    26     s = 0;
    27     while (s + len<n) //至少有两个有序段 
    28     {
    29         e = s + 2 * len - 1;
    30         if (e >= n) //最后一段可能少于len个结点 
    31             e = n - 1;
    32         MergeStep(a, r, s, s + len - 1, e); //相邻有序段合并 
    33         s = e + 1; //下一对有序段中左段的开始下标 
    34     }
    35     if (s<n) //还剩一个有序段,将其从A中复制到R中 
    36     for (; s<n; s++)
    37         r[s] = a[s];
    38 }
    39 void MergeSort(int a[], int n)
    40 {
    41     int *p;
    42     int len = 1;     //有序序列的长度 
    43     int f = 0;    //变量f作标志
    44     if (!(p = (int *)malloc(sizeof(int)*n)))    //分配内存空间,保存临时数据
    45     {
    46         printf("分配临时内存失败!
    ");
    47         exit(0);
    48     }
    49     while (len<n)
    50     {
    51         if (f)   //交替地在A和P之间来回合并 
    52             MergePass(p, a, n, len);    //调用MergePass,对p合并到a
    53         else
    54             MergePass(a, p, n, len);    //调用MergePass,对a合并到p
    55         len *= 2;    //增加有序序列长度
    56         f = 1 - f; //使f值在0和1之间切换 
    57     }
    58     if (f)    //若进行了排序
    59     for (f = 0; f<n; f++)    //将数组p中的数据复制到数组a
    60         a[f] = p[f];
    61     free(p); //释放分配的内存 
    62 }
    63 
    64 int main()
    65 {
    66     int i, a[ARRAYLEN] = {69,65,90,37,92,6,28,54};
    67     printf("原数据:");
    68     for (i = 0; i<ARRAYLEN; i++)
    69         printf("%d ", a[i]);
    70     printf("
    ");
    71 
    72     MergeSort(a,ARRAYLEN);
    73     printf("排序后:");
    74     for (i = 0; i<ARRAYLEN; i++)
    75         printf("%d ", a[i]);
    76     printf("
    ");
    77 
    78     getch();
    79     return 0;
    80 }

     

     

  • 相关阅读:
    程序员追求的是什么?
    jQuery弹出层始终垂直居中,相对于屏幕,相对于当前窗口
    在VMware上制作一个简单的Linux
    Nginx 反向代理+Varnish 技术
    在做微信分享到朋友圈时,手机扫码报config:invalid signature,分享后后正常的问题,是url问题...
    phpStudy本地环境测试,打开网页很慢的解决办法!
    windows上安装redis并安装php5.6的redis扩展
    Redis 安装
    redis 查看的版本
    who is 规格严格
  • 原文地址:https://www.cnblogs.com/swifthua/p/7652863.html
Copyright © 2020-2023  润新知