730 likes | 923 Views
第十二讲 : 排序实现 、 多维数组. 北京大学 信息科学技术学院 20 12 年 11 月. 利用 数组 , 对一组数据 进行排序. 冒泡排序法 选择排序法 归并排序法. 如何把大象关在冰箱里 ?. 排序的基本方法. 分3步: 第一步: 打开冰箱门 ; 第二步: 把大象推进冰箱 ; 第三步: 关上冰箱门 ;. int sz [ LEN ]; // #define LEN 8. 排序的基本方法. 7. 11. 18. 6. 12. 17. 分8个步骤进行 第 1 步:把 第1大 的数放在变量 sz[7] 中;
E N D
第十二讲:排序实现、多维数组 北京大学信息科学技术学院 2012年11月
利用数组,对一组数据进行排序 冒泡排序法 选择排序法 归并排序法
如何把大象关在冰箱里? 排序的基本方法 • 分3步: • 第一步:打开冰箱门; • 第二步:把大象推进冰箱; • 第三步:关上冰箱门;
int sz[LEN]; //#define LEN8 排序的基本方法 7 11 18 6 12 17 • 分8个步骤进行 • 第1步:把第1大的数放在变量sz[7]中; • 第2步:把第2大的数放在变量sz[6]中; • 第3步:把第3大的数放在变量sz[5]中; • 第4步:把第4大的数放在变量sz[4]中; • 第5步:把第5大的数放在变量sz[3]中; • 第6步:把第6大的数放在变量sz[2]中; • 第7步:把第7大的数放在变量sz[1]中; • 第8步:把第8大的数放在变量sz[0]中; 5 13 16 4 17 15 3 18 14 2 14 13 1 15 12 0 16 11 编号 排序前 的值 排序后 的值
排序的基本方法 int sz[LEN]; //#define LEN8 • 分8个步骤进行 • 第1步:把第1大的数放在变量sz[7]中; • 第2步:把第2大的数放在变量sz[6]中; • 第3步:把第3大的数放在变量sz[5]中; • 第4步:把第4大的数放在变量sz[4]中; • 第5步:把第5大的数放在变量sz[3]中; • 第6步:把第6大的数放在变量sz[2]中; • 第7步:把第7大的数放在变量sz[1]中; • 第8步:把第8大的数放在变量sz[0]中; • 分LEN个步骤进行 • 第1步:把第1大的数放在变量sz[LEN-1]中; • 第2步:把第2大的数放在变量sz[LEN-2]中; • 第3步:把第3大的数放在变量sz[LEN-3]中; • 第4步:把第4大的数放在变量sz[LEN-4]中; • 第5步:把第5大的数放在变量sz[LEN-5]中; • 第6步:把第6大的数放在变量sz[LEN-6]中; • …… • 第LEN步:把第LEN大的数放在变量sz[0]中;
排序的基本方法 • 分LEN个步骤进行 • 第1步:把第1大的数放在变量sz[LEN-1]中; • 第2步:把第2大的数放在变量sz[LEN-2]中; • 第3步:把第3大的数放在变量sz[LEN-3]中; • 第4步:把第4大的数放在变量sz[LEN-4]中; • 第5步:把第5大的数放在变量sz[LEN-5]中; • 第6步:把第6大的数放在变量sz[LEN-6]中; • …… • 第LEN步:把第LEN大的数放在变量sz[0]中;
排序的基本方法 对数组intsz[LEN]进行排序, 可以分为LEN 个步骤进行。 第k步:把第k 大的数放在变量 sz[LEN-k] 中; (K=1, 2, 3, 4, …, LEN-1, LEN)
用冒泡法作第1步: 把第1大的数放在变量sz[LEN-1]中; int e; for(int i = 0; i < LEN - 1; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }
用冒泡法作第2步: 把第2大的数放在变量sz[LEN-2]中; int e; for(int i = 0; i < LEN - 2; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }
用冒泡法作第3步: 把第3大的数放在变量sz[LEN-3]中; int e; for(int i = 0; i < LEN - 3; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }
用冒泡法作第k步: 把第k大的数放在变量sz[LEN-k]中; int e; for(int i = 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(int i = 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(int i = 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(int i = 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(;;){ for(int i = 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(int k = ; k <= ; k++){ for(inti= 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(int k = 1 ; k <= ; k++){ for(inti= 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(int k = 1 ; k <= LEN ; k++){ for(int i = 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } } }
用冒泡法对数组intsz[LEN]进行排序 int e; for(int k = 1 ; k <= LEN ; k++){ for(int i = 0; i < LEN - k; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } } } 对该算法进行测试 编写一个程序: 1.从控制台输入一组 数据,并将其存放 一个数组中; 2.用左侧算法进行排 序; 3.打印出排序结果;
排序的基本方法 对数组intsz[LEN]进行排序, 可以分为LEN 个步骤进行。 第k步:把第k 大的数放在变量 sz[LEN-k] 中; (K=1, 2, 3, 4, …, LEN-1, LEN)
用选择法作第1步:把第1大的数放在变量sz[LEN-1]中;用选择法作第1步:把第1大的数放在变量sz[LEN-1]中; int maxIndex, e; maxIndex = 0; for(int i = 0; i <= LEN-1; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-1){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-1]; sz[LEN-1] = e; }
用选择法作第2步:把第2大的数放在变量sz[LEN-2]中;用选择法作第2步:把第2大的数放在变量sz[LEN-2]中; int maxIndex, e; maxIndex = 0; for(int i = 0; i <= LEN-2; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-2){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-2]; sz[LEN-2] = e; }
用选择法作第3步:把第3大的数放在变量sz[LEN-3]中;用选择法作第3步:把第3大的数放在变量sz[LEN-3]中; int maxIndex, e; maxIndex = 0; for(int i = 0; i <= LEN-3; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-3){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-3]; sz[LEN-3] = e; }
用选择法作第k步:把第k大的数放在变量sz[LEN-k]中;用选择法作第k步:把第k大的数放在变量sz[LEN-k]中; int maxIndex, e; maxIndex = 0; for(int i = 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; }
用选择法对数组intsz[LEN]进行排序; int maxIndex, e; maxIndex = 0; for(int i = 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; }
用选择法对数组intsz[LEN]进行排序; int maxIndex, e; maxIndex = 0; for(int i = 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; }
用选择法对数组intsz[LEN]进行排序; int maxIndex, e; maxIndex = 0; for(int i = 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; }
用选择法对数组intsz[LEN]进行排序; int maxIndex, e; for(;;){ maxIndex = 0; for(int i = 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; } }
用选择法对数组intsz[LEN]进行排序; intmaxIndex, e; for(int k = ; k <= ; k++){ maxIndex= 0; for(inti= 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex= i; } } if(maxIndex!= LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; } }
用选择法对数组intsz[LEN]进行排序; int maxIndex, e; for(int k = 1 ; k <= LEN; k++){ maxIndex = 0; for(int i = 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; } }
用选择法对数组intsz[LEN]进行排序; int maxIndex, e; for(int k = 1 ; k <= LEN; k++){ maxIndex = 0; for(int i = 0; i <= LEN-k; i++){ if(sz[i] >sz[maxIndex]){ maxIndex = i; } } if(maxIndex != LEN-k){ e = sz[maxIndex]; sz[maxIndex] = sz[LEN-k]; sz[LEN-k] = e; } } 对该算法进行测试 编写一个程序: 1.从控制台输入一组 数据,并将其存放 一个数组中; 2.用左侧算法进行排 序; 3.打印出排序结果;
归并排序的思想 • 如果只有一个数,则已经排好序,结束; • 递归的把前一半数排好序; • 递归的把后一半数排好序; • 把前后两个排好序的部分按序合并在一起。
归并排序示例 1 4 2 7 3 5 8 6
归并排序示例 1 4 2 7 3 5 8 6 把数组分为前后两部分
归并排序示例 1 2 4 7 3 5 6 8 递归的把前半部分排好序 递归的把后半部分排好序
归并排序示例 1 2 4 7 3 5 6 8 再把两部分归并到一起
归并排序示例 1 2 4 7 3 5 6 8
归并排序示例 1 2 4 7 3 5 6 8 1
归并排序示例 1 2 4 7 3 5 6 8 1 2
归并排序示例 1 2 4 7 3 5 6 8 1 2 3
归并排序示例 1 2 4 7 3 5 6 8 1 2 3 4
归并排序示例 1 2 4 7 3 5 6 8 1 2 3 4 5
归并排序示例 1 2 4 7 3 5 6 8 1 2 3 4 5 6
归并排序示例 1 2 4 7 3 5 6 8 1 2 3 4 5 6 7
归并排序示例 1 2 4 7 3 5 6 8 1 2 3 4 5 6 7 8
#include <stdio.h> • #define MAX 1000/* 最大数组大小 */ • voidmerge_sort(inta[], intfrom, intto); /* 函数声明 */ • intmain() • { • inta[MAX]; /* 定义数组 */ • inti, n; • scanf("%d", &n); /* 读入数的个数 */ • for (i = 0; i < n; i++) { /* 把数读入数组 */ • scanf("%d", &a[i]); • } • merge_sort(a, 0, n); /* 调用归并排序函数 */ • for (i = 0; i < n; i++) { /* 把排好序的数输出 */ • printf("%d\n", a[i]); • } • return 0; • }
/* 合并函数声明,将数组a中排好序的两个部分合并 */ voidmerge(inta[], intfrom, intmid, intto); /* 归并排序函数,递归的将数组a中从from到to间的数排序 */ voidmerge_sort(inta[], intfrom, intto) { if ((to - from) == 1) /* 如果只有一个数,直接返回 */ return; intmid = (from + to) / 2;/* 计算中间点位置 */ merge_sort(a, from, mid); /* 递归的排序前半部分 */ merge_sort(a, mid, to); /* 递归的排序后半部分 */ merge(a, from, mid, to); /* 将前后两部分归并到数组a中 */ }
intt[MAX];/* 全局临时数组,用于暂存合并结果 */ /* 合并函数声明,将数组a中排好序的两个部分合并 */ void merge(inta[], intfrom, intmid, intto) { inti = from, j = mid, k = from; while (i < mid && j < to) { /* 两部分都还有剩余的数 */ if (a[i] < a[j]) { t[k++] = a[i++]; /* 前半部分的当前数更小,复制到目标数组 */ } else { t[k++] = a[j++]; /* 后半部分的当前数更小,复制到目标数组 */ } } while (i < mid) { /* 只有前半部分都还有剩余的数 */ t[k++] = a[i++]; /* 把剩余的数复制到目标数组 */ } while (j < to) { /* 只有后半部分都还有剩余的数 */ t[k++] = a[j++]; /* 把剩余的数复制到目标数组 */ } for (i = from; i < to; i++) { /* 把归并结果复制到数组t中 */ a[i] = t[i]; } }