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 }

 

 

原文地址:https://www.cnblogs.com/swifthua/p/7652863.html