第3章 排序==归并排序
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
SR[s..t]平分为两部分SR[s..m]、SR[m+1..t]后,再归
并为TR[s..t]。这样平分为递归过程。 合并Merge 7
归并排序的算法
如果记录无序序列 SR[s..t] 的两部分 SR[s .. (s+t)/2 ] 和 SR[ (s+t)/2+1 .. t] 已经分别按关键字有序, 则利用上述归并算法很容易将它们归并成 整个记录序列是一个有序序列。
else
{m = (s+t)/2; // 将SR[s..t]平分为SR[s..m]和SR[m+1..t]
Msort (SR, TR2, s, m); // 递归地将Sቤተ መጻሕፍቲ ባይዱ[s..m]归并为有序的TR2[s..m]
Msort (SR, TR2, m+1, t); //递归地SR[m+1..t]归并为有序的TR2[m+1..t]
{2-路归并排序的核心操作:将一维数 组// 将中相前邻后的相SR邻中的记两录由个小有到序大充归列并归为并TR 为一if (个SR有[i序].k序ey列<=。SR[j].key) TR[k] = SR[i++];
else TR[k] = SR[j++];
4
}
算法3.9 void Merge (RcdType SR[], RcdType TR[],
int i, int m, int n) { // 将相邻有序的记录序列 SR[i..m] 和 SR[m+1..n] // 归并为有序的记录序列 TR[i..n]
for (j=m+1, k=i; i<=m && j<=n; ++k)
{
// 将SR中记录由小到大归并为TR
if (SR[i].key<=SR[j].key) TR[k] = SR[i++];
有序序列R[1..i]
无序序列 R[i+1..n] 13
简单选择排序的算法描述如下:
void SelectSort (Elem R[], int n ) { // 对记录序列R[1..n]作简单选择排序。
for (i=1; i<n; ++i) { // 选择第 i 小的记录,并交换到位
j = SelectMinKey(R, i); // 在 R[i..n] 中选择关键字最小的记录
Merge (TR2, TR1, s, m, t);
// 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t]
}
9
} // Msort
void MergeSort (SqList &L) {
// 对顺序表 L 作2-路归并排序
Msort(L.r, L.r, 1, L.length); } // MergeSort
MSort(SR,TR2,1,4)
MSort(SR,TR2,5,7)
49,38,65,97
Merge(TR2,TR1,1,4,7)
MSort(SR,TR2,1,2)
49,38
MSort(SR,TR2,3,4)
65,97
Merge(TR2,TR1,1,2,4)
38,49,65,97
MSort(SR,TR2,1,1)
由此,应该先分别对这两部分进行 2-路归 并排序。
8
void Msort ( RcdType SR[], RcdType TR1[], int s, int t ) {
// 将SR[s..t] 归并排序为 TR1[s..t]
RcdType *TR2=new RcdType[t-s+1];
if (s= =t) TR[s]=SR1[s];
归并排序过程
SR[1] SR[2] SR[3] SR[4] SR[5] SR[6] SR[7]
<初态> 49 38 65 97 76 13 27
第1次平分( 49 38 65 97)( 76 13 27 )
第2次平分( 49 38 )( 65 97)( 76 13)( 27 )
第3次平分( 49)(38 )( 65)(97)( 76)( 13)( 27 )
49
MSort(SR,TR2,2,2)
38
Merge(TR2,TR1,1,1,2) 11
38,49
三、堆排序
简单选择排序 堆排序
(具体实现细节见第6章)
12
一、简单选择排序
假设排序过程中,待排记录序列的状态为:
有序序列R[1..i-1]
第i趟 简单选择排序
无序序列 R[i..n]
从中选出 关键字最小的记录
可以得出,对 n 个记录进行归并排序 的时间复杂度为Ο(nlogn)。即:
每一趟归并的时间复杂度为 O(n), 总共需进行 logn 趟。
10
例如,对线性表L:49,38,65,97,76,13,27,进行归并 排序执行过程:
MSort(L.r,L.r,1,7)
49,38,65,97,76,13,27
<初态> (49) (38) (65) (97) (76) (13) (27)
<第1趟> (38 49) (65 97) (13 76) (27)
<第2趟> (38 49 65 97) (13 27 76)
fo<r第(3j=趟m>+1(,1k3 =i;27i<=m38 &&49j<=6n5; ++7k6) 97)
二、归并排序 归并排序的过程基于下列基本思想进行: 将两个或两个以上的有序表 “归并”
为一个新的有序表。
1
在内部排序中,通常采用的是2-路归并 排序。即:将两个位置相邻的记录有序子序 列
有序子序列 R[l..m] 有序子序列 R[m+1..n]
归并为一个记录的有序序列。 有 序 序 列 R[l..n]
else TR[k] = SR[j++];
}
5
if (i<=m) TR[k..n] = SR[i..m]; // 将剩余的 SR[i..m] 复制到 TR
if (j<=n) TR[k..n] = SR[j..n]; // 将剩余的 SR[j..n] 复制到 TR
} // Merge
6
平分MSort
这个操作对顺序表而言,是轻而易举的。 2
❖基本思想:将一个具有n个待排 序记录的序列看成是n个长度为1 的有序序列,然后进行两两归并, 得到n/2个长度为2的有序序列, 再进行两两归并,…如此重复, 直至得到一个长度为n的有序序 列为止。
❖这种排序方法称为2-路归并排序。
3
归并排序过程
SR[1] SR[2] SR[3] SR[4] SR[5] SR[6] SR[7]
并为TR[s..t]。这样平分为递归过程。 合并Merge 7
归并排序的算法
如果记录无序序列 SR[s..t] 的两部分 SR[s .. (s+t)/2 ] 和 SR[ (s+t)/2+1 .. t] 已经分别按关键字有序, 则利用上述归并算法很容易将它们归并成 整个记录序列是一个有序序列。
else
{m = (s+t)/2; // 将SR[s..t]平分为SR[s..m]和SR[m+1..t]
Msort (SR, TR2, s, m); // 递归地将Sቤተ መጻሕፍቲ ባይዱ[s..m]归并为有序的TR2[s..m]
Msort (SR, TR2, m+1, t); //递归地SR[m+1..t]归并为有序的TR2[m+1..t]
{2-路归并排序的核心操作:将一维数 组// 将中相前邻后的相SR邻中的记两录由个小有到序大充归列并归为并TR 为一if (个SR有[i序].k序ey列<=。SR[j].key) TR[k] = SR[i++];
else TR[k] = SR[j++];
4
}
算法3.9 void Merge (RcdType SR[], RcdType TR[],
int i, int m, int n) { // 将相邻有序的记录序列 SR[i..m] 和 SR[m+1..n] // 归并为有序的记录序列 TR[i..n]
for (j=m+1, k=i; i<=m && j<=n; ++k)
{
// 将SR中记录由小到大归并为TR
if (SR[i].key<=SR[j].key) TR[k] = SR[i++];
有序序列R[1..i]
无序序列 R[i+1..n] 13
简单选择排序的算法描述如下:
void SelectSort (Elem R[], int n ) { // 对记录序列R[1..n]作简单选择排序。
for (i=1; i<n; ++i) { // 选择第 i 小的记录,并交换到位
j = SelectMinKey(R, i); // 在 R[i..n] 中选择关键字最小的记录
Merge (TR2, TR1, s, m, t);
// 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t]
}
9
} // Msort
void MergeSort (SqList &L) {
// 对顺序表 L 作2-路归并排序
Msort(L.r, L.r, 1, L.length); } // MergeSort
MSort(SR,TR2,1,4)
MSort(SR,TR2,5,7)
49,38,65,97
Merge(TR2,TR1,1,4,7)
MSort(SR,TR2,1,2)
49,38
MSort(SR,TR2,3,4)
65,97
Merge(TR2,TR1,1,2,4)
38,49,65,97
MSort(SR,TR2,1,1)
由此,应该先分别对这两部分进行 2-路归 并排序。
8
void Msort ( RcdType SR[], RcdType TR1[], int s, int t ) {
// 将SR[s..t] 归并排序为 TR1[s..t]
RcdType *TR2=new RcdType[t-s+1];
if (s= =t) TR[s]=SR1[s];
归并排序过程
SR[1] SR[2] SR[3] SR[4] SR[5] SR[6] SR[7]
<初态> 49 38 65 97 76 13 27
第1次平分( 49 38 65 97)( 76 13 27 )
第2次平分( 49 38 )( 65 97)( 76 13)( 27 )
第3次平分( 49)(38 )( 65)(97)( 76)( 13)( 27 )
49
MSort(SR,TR2,2,2)
38
Merge(TR2,TR1,1,1,2) 11
38,49
三、堆排序
简单选择排序 堆排序
(具体实现细节见第6章)
12
一、简单选择排序
假设排序过程中,待排记录序列的状态为:
有序序列R[1..i-1]
第i趟 简单选择排序
无序序列 R[i..n]
从中选出 关键字最小的记录
可以得出,对 n 个记录进行归并排序 的时间复杂度为Ο(nlogn)。即:
每一趟归并的时间复杂度为 O(n), 总共需进行 logn 趟。
10
例如,对线性表L:49,38,65,97,76,13,27,进行归并 排序执行过程:
MSort(L.r,L.r,1,7)
49,38,65,97,76,13,27
<初态> (49) (38) (65) (97) (76) (13) (27)
<第1趟> (38 49) (65 97) (13 76) (27)
<第2趟> (38 49 65 97) (13 27 76)
fo<r第(3j=趟m>+1(,1k3 =i;27i<=m38 &&49j<=6n5; ++7k6) 97)
二、归并排序 归并排序的过程基于下列基本思想进行: 将两个或两个以上的有序表 “归并”
为一个新的有序表。
1
在内部排序中,通常采用的是2-路归并 排序。即:将两个位置相邻的记录有序子序 列
有序子序列 R[l..m] 有序子序列 R[m+1..n]
归并为一个记录的有序序列。 有 序 序 列 R[l..n]
else TR[k] = SR[j++];
}
5
if (i<=m) TR[k..n] = SR[i..m]; // 将剩余的 SR[i..m] 复制到 TR
if (j<=n) TR[k..n] = SR[j..n]; // 将剩余的 SR[j..n] 复制到 TR
} // Merge
6
平分MSort
这个操作对顺序表而言,是轻而易举的。 2
❖基本思想:将一个具有n个待排 序记录的序列看成是n个长度为1 的有序序列,然后进行两两归并, 得到n/2个长度为2的有序序列, 再进行两两归并,…如此重复, 直至得到一个长度为n的有序序 列为止。
❖这种排序方法称为2-路归并排序。
3
归并排序过程
SR[1] SR[2] SR[3] SR[4] SR[5] SR[6] SR[7]