《算法导论》(CLRS)第三版 第1、2章总结(二)

5. 归并排序 (Merge Sort)

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3
 4 void print(int arr[], int n) {
 5     int i;
 6     for (i = 0; i < n; i++) {
 7         printf("%d ", arr[i]);
 8     }
 9     printf("\n");
10 }
11
12 void merge(int arr[], int s, int n) {
13     int* L = (int*)malloc(s * sizeof(int));
14     int* R = (int*)malloc((n-s) * sizeof(int));
15     int i, j, k, t = n - s;
16     for (i = 0; i < s; i++) {
17         L[i] = arr[i];
18     }
19     for (j = 0; i < n; i++, j++) {
20         R[j] = arr[i];
21     }
22     i = j = k = 0;
23     while (i < s && j < t) {
24         if (L[i] <= R[j]) {
25             arr[k++] = L[i++];
26         } else {
27             arr[k++] = R[j++];
28         }
29     }
30     while (i < s) {
31         arr[k++] = L[i++];
32     }
33     while (j < t) {
34         arr[k++] = R[j++];
35     }
36     free(L), free(R);
37 }
38
39 void merge_sort(int arr[], int n) {
40     if (n > 1) {
41         int s = n / 2, t = (n+1) / 2;
42         merge_sort(arr, s);
43         merge_sort(arr+s, t);
44         merge(arr, s, n); // [0, s) & [s, n)
45     }
46 }
47
48 int main() {
49     int arr[10] = {1, 4, 2, 8, 5, 7, 9, 3, 0, 6};
50     int n = 10;
51     merge_sort(arr, n);
52     print(arr, n);
53     return 0;
54 }

上面程序中,merge_sort 的时间复杂度为 O(nlgn), 空间复杂度为 O(nlgn)。
下面给出一种原地归并排序的C语言代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3
 4 void print(int arr[], int n) {
 5     int i;
 6     for (i = 0; i < n; i++) {
 7         printf("%d ", arr[i]);
 8     }
 9     printf("\n");
10 }
11
12 void reverse(int arr[], int n) {
13     int i = 0, j = n-1;
14     while (i < j) {
15         int t = arr[i];
16         arr[i] = arr[j];
17         arr[j] = t;
18         i++, j--;
19     }
20 }
21
22 void rotate(int arr[], int n, int k) {
23     reverse(arr, n-k);
24     reverse(arr+n-k, k);
25     reverse(arr, n);
26 }
27
28 void merge(int arr[], int s, int n) {
29     int i = 0, j = s, k = s;
30     while (j < n) {
31         while (i < j && arr[i] <= arr[j]) i++;
32         if (i == j) break;
33         while (j < n && arr[j] < arr[i]) j++;
34         rotate(arr+i, j-i, j-k);
35         i += j-k, k = j;
36     }
37 }
38
39 void merge_sort(int arr[], int n) {
40     if (n > 1) {
41         int s = n / 2, t = (n+1) / 2;
42         merge_sort(arr, s);
43         merge_sort(arr+s, t);
44         merge(arr, s, n); // [0, s) & [s, n)
45     }
46 }
47
48 int main() {
49     int arr[10] = {1, 4, 2, 8, 5, 7, 9, 3, 0, 6};
50     int n = 10;
51     merge_sort(arr, n);
52     print(arr, n);
53     return 0;
54 }

6. 冒泡排序 (Bubble Sort)

 1 void bubble_sort(int arr[], int n) {
 2     int i, j;
 3     for (i = 0; i < n; i++) {
 4         for (j = n-1; j > i; j--) {
 5             if (arr[j] < arr[j-1]) {
 6                 int tmp = arr[j];
 7                 arr[j] = arr[j-1];
 8                 arr[j-1] = tmp;
 9             }
10         }
11     }
12 }

对其做一点小的优化,使得最好情况下时间复杂度为 O(n),平均情况下执行时间有所减少,但是不会改变平均情况和最坏情况下渐近复杂度的上界 O(n^2)。

 1 void bubble_sort(int arr[], int n) {
 2     int i, j;
 3     for (i = 0; i < n; i++) {
 4         int flag = 0;
 5         for (j = n-1; j > i; j--) {
 6             if (arr[j] < arr[j-1]) {
 7                 int tmp = arr[j];
 8                 arr[j] = arr[j-1];
 9                 arr[j-1] = tmp;
10                 flag = 1;
11             }
12         }
13         if (flag == 0) break;
14     }
15 }

7. 选择排序 (Selection Sort)

 1 void what_sort(int arr[], int n) {
 2     int i, j;
 3     for (i = 0; i < n; i++) {
 4         for (j = i+1; j < n; j++) {
 5             if (arr[i] > arr[j]) {
 6                 int tmp = arr[i];
 7                 arr[i] = arr[j];
 8                 arr[j] = tmp;
 9             }
10         }
11     }
12 }
13
14 void selection_sort(int arr[], int n) {
15     int i, j;
16     for (i = 0; i < n; i++) {
17         int mini = i, tmp = arr[i];
18         for(j = i+1; j < n; j++) {
19             if (arr[j] < arr[mini]) {
20                 mini = j;
21             }
22         }
23         arr[i] = arr[mini];
24         arr[mini] = tmp;
25     }
26 }

what_sort 其实也是一种选择排序,但是它在性能上比 selection_sort 差一些。

8. 逆序对 (Inversions)

在一个序列 A[0 .. n-1] 中,对任意 i, j, 若 i < j 且 A[i] > A[j], 那么 A[i] 和 A[j] 构成一个逆序对。
求序列的逆序对数的最简单的方法就是枚举,时间复杂度为 O(n^2)。

 1 int count_inversions(int arr[], int n) {
 2     int inversions = 0;
 3     int i, j;
 4     for (i = 0; i < n; i++) {
 5         for (j = i+1; j < n; j++) {
 6             if (arr[i] > arr[j]) inversions++;
 7         }
 8     }
 9     return inversions;
10 }

在合并排序的基础上做一些修改,我们能得到一个时间复杂度为O(nlgn)的算法:

 1 void reverse(int arr[], int n) {
 2     int i = 0, j = n-1;
 3     while (i < j) {
 4         int t = arr[i];
 5         arr[i] = arr[j];
 6         arr[j] = t;
 7         i++, j--;
 8     }
 9 }
10
11 void rotate(int arr[], int n, int k) {
12     reverse(arr, n-k);
13     reverse(arr+n-k, k);
14     reverse(arr, n);
15 }
16
17 int merge(int arr[], int s, int n) {
18     int inversions = 0;
19     int i = 0, j = s, k = s;
20     while (j < n) {
21         while (i < j && arr[i] <= arr[j]) i++;
22         if (i == j) break;
23         while (j < n && arr[j] < arr[i]) j++;
24         rotate(arr+i, j-i, j-k);
25         inversions += (j-k) * (k-i);
26         i += j-k, k = j;
27     }
28     return inversions;
29 }
30
31 int count_inversions(int arr[], int n) {
32     int inversions = 0;
33     if (n > 1) {
34         int s = n / 2, t = (n + 1) / 2;
35         inversions += count_inversions(arr, s);
36         inversions += count_inversions(arr+s, t);
37         inversions += merge(arr, s, n);
38     }
39     return inversions;
40 }

* 最后,顺便提一下,本文所介绍的三种排序算法都是稳定的。

《算法导论》(CLRS)第三版 第1、2章总结(二)

时间: 2024-08-25 00:10:13

《算法导论》(CLRS)第三版 第1、2章总结(二)的相关文章

算法导论(第三版)Excercies2.2

2.2-1: Θ (n3) 2.2-2:插入排序 void selectionSort(int a[], int n) { int i, j, k, key; for(i=0; i<n-1; i++) { k = i; for(j=i+1; j<n; j++) if(a[k] > a[j]) k = j; if(k != i) { key = a[k]; a[k] = a[i]; a[i] = key; } } } 最佳情况:Θ(n2) 最差情况:Θ(n2) 2.2-3:线性排序 平均情

算法导论_第三版PDF

因为csdn资源限制了大小,文件无法上传,所以只能上传到第三方了,文件大小是99M,在网上找了很长时间才找到的,是完整版哦,之前下载的都是不全的,这个是完整的 点击进入下载页面

算法导论(CLRS)答案

算法导论(CLRS)答案 Chapter Section I 1 2 p II 1 2 3 p III 1 2 p IV 1 2 3 4 p V 1 2 3 4 p VI 1 2 3 4 5 p VII 1 2 3 4 p VIII 1 2 3 4 p IX 1 2 3 p XII 1 2 3 XIII 1 2 3 4 p 假设你有兴趣,能够选一个章节去完毕. 欢迎watch/fork/star/contribute我的项目. 欢迎挑错. Follow @louis1992 on github

《深入理解计算机系统(第三版)》第二章 信息的表示和处理

<深入理解计算机系统(第三版)>第二章 信息的表示和处理 ??计算机本身是由处理器和存储器子通过系统组成.在核心部分,我们需要方法来表示基本数据类型,比如整数和实数运算的近似值.然后,我们考虑机器级指令如何操作这样的数据,以及编译器又如何将C程序翻译成这样的指令.接下来,研究几种实现处理器的方法,帮助我们更好的了解硬件资源如何被用来执行指令.理解了编译器和机器级代码,我们就能了解如何通过编写C程序以及编译它们来最大化程序的性能.本章主要使我了解了如何表示和执行应用程序,通过一些技巧,来写出安全

算法导论部分总结图片版

我们的算法导论:(中文版下载链接) 目录(Table of Contents)前言(Preface)第一部分(Part I) 基础(Foundations)第一章 计算中算法的角色(The Role of Algorithms in Computing)第二章 开始(Getting Started)第三章 函数的增长率(Growth of Functions)第四章 递归(Recurrences)第五章 概率分析与随机化算法(Probabilistic Analysis and Randomiz

[Algorithm] 如何正确撸&lt;算法导论&gt;CLRS

其实算法本身不难,第一遍可以只看伪代码和算法思路.如果想进一步理解的话,第三章那些标记法是非常重要的,就算要花费大量时间才能理解,也不要马马虎虎略过.因为以后的每一章,讲完算法就是这样的分析,精通的话,很快就读完了.你所说的证明和推导大概也都是在第三章介绍了,可以回过头再认真看几遍. 至于课后题,比较难,我只做了前几章,如果要做完需要更多时间和精力.这可以通过之后做算法题来弥补,可以去leetcode等网站找一些经典的算法题做一做,加深理解. Facebook的工程师写的攻略,介绍了用算法导论来

重读《学习JavaScript数据结构与算法-第三版》-第2章 ES和TS

定场诗 八月中秋白露,路上行人凄凉: 小桥流水桂花香,日夜千思万想. 心中不得宁静,清早览罢文章, 十年寒苦在书房,方显才高志广. 前言 洛伊安妮·格罗纳女士所著的<学习JavaScript数据结构与算法>第三版于2019年的5月份再次刊印发行,新版内容契合当下,实为JavaScript开发人员的必备之佳作.有幸重读此版,与诸君分享共勉. 内容提要 此章节为第2章-ECMAScript与TypeScript概述,主要介绍了JS和TS的相关概念,以及在JS新版本中的新特性:let.解构.箭头函数

算法导论CLRS答案

目前正在编写算法导论答案,欢迎大家follow me at mygithub 刚完成第9章,中位数和顺序统计学 正在编写第13章,红黑树 想要参与的朋友可以告诉我想要编写的章节,开个branch给你------

王爽《汇编语言》第三版 第十五章 外中断

引言 CPU 除了有运算能力外,还要有 I/O( Input/Output ,输入/输出)能力. 15.1 接口芯片和端口 在PC系统的接口卡和主板上,装有各种接口芯片.这些外设接口芯片的内部有若干寄存器,CPU将这些寄存器当作端口来访问. 外设的输入不直接送入内存和CPU ,而是送入相关的接口芯片的端口中. CPU向外设的输出也不是直接送入外设,而是先送入端口中,再由相关的芯片送到外设. 15.2 外中断信息 当CPU 检测到可屏蔽中断信息时: 1.如果IF=1,则CPU 在执行完当前指令后响