176
8.1 概概 8.2 概概概概 8.3 概概概概概概概概概概概概概 8.4 概概概概概概概概 8.5 概概概概概概概概概 8.6 概概概概 8.7 概概概概 概概概 概概

8.1 概述 8.2 合并排序 8.3 用比较法进行排序的时间下界 8.4 选择排序和堆排序 8.5 插入排序和希尔排序 8.6 快速排序 8.7 基数排序

  • Upload
    rumer

  • View
    394

  • Download
    12

Embed Size (px)

DESCRIPTION

第八章 排序. 8.1 概述 8.2 合并排序 8.3 用比较法进行排序的时间下界 8.4 选择排序和堆排序 8.5 插入排序和希尔排序 8.6 快速排序 8.7 基数排序. 概述. 排序:内部排序:全部记录都可以同时调入内存进行的排序。 外部排序:文件中的记录太大,无法全部将其同时调入内存进行的排序。. 定义:设有记录序列: { R 1 、 R 2 ……….. R n } 其相应的关键字序列为: - PowerPoint PPT Presentation

Citation preview

Page 1: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

8.1 概述 8.2 合并排序 8.3 用比较法进行排序的时间下界 8.4 选择排序和堆排序8.5 插入排序和希尔排序8.6 快速排序8.7 基数排序

第八章 排序

Page 2: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

概述• 排序:内部排序:全部记录都可以同时调入内存进行的排序。 外部排序:文件中的记录太大,无法全部将其同时调入内存进行的排序。• 定义:设有记录序列: { R1 、 R2 ……….. Rn } 其相应的关键字序列为: { K1 、 K2 ……….. Kn }; 若存在一种确定的关系: Kx <= Ky <= … <= Kz

则将记录序列 { R1 、 R2 ……….. Rn } 排成按该关键字有序的序列: { Rx 、 Ry ……….. Rz } 的操作,称之为排序。

关系是任意的,如通常经常使用的小于、大于等关系或任意的关系。

• 稳定与不稳定:若记录序列中的任意两个记录 Rx 、 Ry 的关键字 Kx = Ky ;如果在 排序之前和排序之后,它们的相对位置保持不变,则这种排序方法 是稳定的,否则是不稳定的。

Page 3: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

3

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

Page 4: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

4

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7

Page 5: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

5

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7

Page 6: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

6

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13

Page 7: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

7

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13

Page 8: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

8

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49

Page 9: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

9

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49

Page 10: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

10

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49 65

Page 11: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

11

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49 65

Page 12: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

12

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49 65 76

Page 13: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

13

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49 65 76

Page 14: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

14

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49 65 76 80

Page 15: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

15

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49 65 76 80

Page 16: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

16

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

0 1 2 3 4

4913 65 97

767 80

A

B

0 1 2 3 4 5 6 7

C

i

j

k

7 13 49 65 76 80 97

Page 17: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

17

合并排序• Merging sort: 思想来源于合并两个已排序的顺序表。•e.g: 将下面两个已排序的顺序表合并成一个已排序表。顺序比较两者的相应元素,小者移入另一表中,反复如此,直至其中任一表都移入另一表为止。

1 2 3 4 54913 65 97A 7

6 7 8 9767 80B 3

1 2 3 4 5 6 7 8 9

C 4913 65 97767 803 7

• 实现很简单, A 、 B 、 C 三表分别设置指针 p 、 q 、 k 初值为 1,6,1 ,比较 p 、 q 指针指向 的结点,将小者放入 C 表 , 相应指针加 1 。如 A 、 B 表中一张表为空,则将另一张表的结点 全部移入 C 表。• 比较次数和移动次数和两张表的结点总数成正比。

Page 18: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

18

合并排序• 合并二张有序表:

template < class EType>

void Merge( EType a[ ], EType aa[ ], int n, int low, int up, int m ) {

int p=low, q=low+m, r;

// 合并 a[low] 至 a[low+m-1] 和 a[low+m] 至 a[up] 。

for (r=1; r<=n; r++) aa[r] = a[r];

r = low; // 数组 a 的初始指针。while ( p < low + m && q < up + 1 ) {

while ( p < low + m && aa[p] <= aa[q] ) a[r++] = aa[p++];

if ( p < low + m ) while ( q < up + 1 && aa[q] < aa[p] ) a[r++] = aa[q++];

}

if ( p = = low + m ) for ( ; q <=up; q++ ) a[r++] = aa[q];

if ( q = = up + 1 ) for ( ; p <=low + m -1; p++ ) a[r++] = aa[p];

}

Page 19: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

19

合并排序 合并排序的基本思想:

1 2 3 4 5 6 7

9 7 8 3 52 4 16

7 9 3 8 4 52 16

3 7 8 9 4 16 52

3 4 7 8 9 16 52

子表长 m : 1

子表长 m : 2

子表长 m : 4

子表长 m : 8

分析: 1 、被合并的二张表中第一张表的起始地址设为 low, 那么第二张表的起始地址应为 low + m, 而 终止地 址通常为 up = low +2m -1 。如果 up>n( 表长 ) ,那么 up = n ;即取二者小者作第二张表的终止地址。 2 、当 up + m >= n 时,意味着下一次被合并的两张表中的第一张表的末地址大于等于最大下标 n ,这说 明被合并的第二张表不存在,意味着本趟结束。要过渡到下一趟合并; m 应增大一倍。 3 、 当子表长 m >= n 时,合并排序结束。

i j

Page 20: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

20

合并排序• 合并排序法:

template < class EType> void MergeSort( EType a[ ], int n ) { // 待排序的表为数组 a, a[0] 不用,待排序的数组元素为 a[1], a[2], ……, a[n] 。 int low=1; // 被合并的二个表中的第一个表的首地址。 int up; // 被合并的二个表中的第二个表的末地址。 int m=1; // 被合并的二个表中的第一个表的表长。初始时为 1 。 EType * aa; aa = new EType[n+1] ; // 用于合并的辅助数组, aa[0] 仍然不用。 while ( m < n ) {

up = min(low + 2 * m –1, n);Merge(a, aa, n, low, up,m); // 将 a[low] 至 a[low+m-1] 和 a[low+m] 至 a[up] 进行合并。if ( up+m < n ) low = up + 1; // up+m ≥ n 意味着被合并的另一张表不存在。else { m *= 2; low = 1; } // 过渡到下一次合并,子表长度增大一倍。

} delete [ ]aa;}

Page 21: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

21

合并排序· 时间复杂性分析:

• 合并的过渡趟数: logn

• 每趟进行时,调用 merge 过程 n / ( 2 * len ) 次, 每次比较和数据移动都是 (2 * len )

次,因此每趟代价为 O( n ) 。• 总的代价为 T(n) = O ( nlogn )

• 在递归的情况下:可通过下式求出时间复杂性的级别。2 for n=2

T(n) =

T( n/2 ) + T( n/2 ) + n else

解上述的递归式,可知时间复杂性为 T(n) = O ( nlogn ) 。当 n 是 2 的整数幂时简化为T(n) = O ( nlogn )

Page 22: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

22

用比较法进行排序的时间下界• 判定树模型:如下图所示,说明对 a,b,c 进行分类的一颗判定树。当判断条件成立时, 转向左,否则转向右。

• 比较法分类的下界: Ω ( n logn )

a < b

a < b < c a < c b < c

a < cb < c

a < c < b c < a < b c < b < a

b < a < c

b < c < a

no yes

yes

yes

yes

yes

no

no

no

no

• 注意:树高代表比较的代价。因此只要知道了树高和结点数 n 的关系,就可以求出 用比较法进行排序时的时间代价。另外, n 个结点的分类序列,其叶子结点 共有 n! 片。

Page 23: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

23

用比较法进行排序的时间下界• 定理:高为 H 的二叉树,最多具有 2(H-1) 片叶子。 证明: H = 1 时,最多 1 片叶子,定理成立。 H = 2 时,最多 2 片叶子,定理成立。

设 H = n-1 时公式成立。则当 H = n 时, 根结点有具有叶子结点最多的高为 n-1 的左 右子树;叶子结点总数为:

2(n-2)×2 = 2(n-1) 公式成立。 推论:具有 N 片叶子的二叉树,高最少为 logN + 1。 或比较次数最少为 logN 。

• 比较法分类的下界: Ω ( n logn )

高为 n-1

具有 2(n-2)

片叶子高为 n-1

具有 2(n-2)

片叶子

H = 1

H = 2

H = n

• 定理:把 n 个不同的结点进行分类的任一判定树的高 度至少为 log(n!) + 1 。 证明: n 个元素的排序序列的总数共有 n! 种,因此在 相应的判定树上至少有 n! 片叶子。根据上述定 理,可证。

推论:用比较的方法对 n 个元素的进行分类。在最坏 情况下至少需要 cnlogn 次比较, 或 Ω(nlogn)

Page 24: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

24

用比较法进行排序的时间下界• 比较法分类的下界: Ω ( n logn )

X 轴

Y 轴 求 y=logx 的积分的示意图

2

1

1 2 3 4

y=logn

1

1 n-1 n

j=1

n n

1

 

log n! = Σ logj ≥ logx dx 不难求出上述积分的值为: nlogn-nloge+loge ≥ nlogn-nloge 。注意到: loge = 1.44 。

Page 25: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

25

简单选择排序• 执行过程:1 2

25 49 25 16 83 4 5

21

25 49 25 16 821

25 49 258 16 21

25 49 25 16 218

rp

rp

16 49 25 25 218

16 49 25 25 218rp

16 21 25 25 498

16 21 25 25 498r p

16 21 25 25 498

16 21 25 25 498r p

16 21 25 25 498

6

Page 26: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

26

template < class EType>

void SelectSort( EType a[ ], int n ) {

int p, q; // p 、 q 为数组 a 的指针。 a[1], a[2 ], …,a[n] 为待排序序列。 a[0] 不用。

int r; // 暂时保存具有最小键值的结点地址。 for ( p = 1; p < n; p++) {

r = p;

for ( q = p+1; q <= n; q++) if ( a[q ] < a[r] ) r = q; // 记住本趟挑选的最小结点的地址。 if ( r !=p ) { a[0] = a[p]; a[p] = a[r]; a[r] = a[0]; } // 若最小结点不是 a[p], 则交换。 }

}

简单选择排序

Page 27: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

27

• 有 n 个元素的数组的比较次数 (n-1) + (n-2) + . . . + 2 + 1 = O(n2)

交换次数 3 (n-1) 因循环执行 (n-1) 次,最坏情况下每次都交换。 总的时间复杂性代价为: O(n2)

简单选择排序

Page 28: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

树型选择排序• 改进:简单选择排序没有利用上次选择的结果,是造成速度慢的主要原因。如果能够 加以改进,将会提高排序的速度。

38 1376 276549 97 49

38 65 13 27

1338

13 选出最小者 13

Page 29: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

树型选择排序• 改进:简单选择排序没有利用上次选择的结果,是造成速度慢的重要原因。如果,能 够加以改进,将会提高排序的速度。由于有更好的排序方法,所以本方法用的 很少。

38 1376 276549 97 49

38 65 13 27

1338

13

选出次最小者,应利用上次比较的结果。从被 13 打败的结点 27 、 76 、 38 中加以确定。

Page 30: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

堆排序• 堆的定义: n 个元素的序列 { k1 , k2 ,…… , kn } ,当且仅当满足以下关系时,称 之为堆:

ki <= k2i ki >= k2i

ki <= k2i+1 ki >= k2i+1

( i = 1,2, …… , n/2 )

且分别称之为最小化堆和最大化堆。 e.g: 序列 { 96,83,27,11,9} 最大化堆

{ 12 , 36 , 24 , 85 , 47 , 30 , 53 , 91} 最小化堆

96

911

83 27 2 3

1

4 5

12

4785

91

36 24

53306

2

7

3

1

8

4 5

Page 31: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

31

70

60

40 30

12

8

最大堆的最大元素

10

Page 32: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

32

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

70

60

12

40

30

8

10

70

1

60

240 4

30

5

12

3

8

6

root

10

7

数组表示的堆

Page 33: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

33

建堆

30

1 60

240 4

70

5

8

3 12

6

10

7

root[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

60

8

40

70

12

10 叶子结点,符合堆的的定义。

不合堆的定义,需调整。即建立小堆。建立的第一个小堆的堆顶的下标为 n/2

数组 h

Page 34: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

34

建堆

30

1

60

240 4

70

5

8

3 12

6

10

7

root[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

60

12

40

70

8

10 叶子结点,符合堆的的定义。

不合堆的定义,需调整。即建立大堆。建立的第一个小堆的堆顶的下标为 n/2

数组 h

Page 35: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

35

建堆

30

1

60

240 4

70

5

12

3 8

6

10

7

root[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

60

12

40

70

8

10

不合堆的定义,需调整。建立以 h[ 2 ] 为堆顶的正确的最大化小堆。

数组 h

Page 36: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

36

建堆

30

1

70

240 4

60

5

12

3 8

6

10

7

root[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

70

12

40

60

8

10

不合堆的定义,需调整。建立以 h[ 2 ] 为堆顶的正确的最大化小堆。

数组 h

Page 37: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

37

建堆

30

1

70

240 4

60

5

12

3 8

6

10

7

root[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

70

12

40

60

8

10

不合堆的定义,需调整。建立以 h[ 1 ] 为堆顶的正确的最大化堆。数组 h

Page 38: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

38

建堆

70

1

30

240 4

60

5

12

3 8

6

10

7

root[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

70

30

12

40

60

8

10

不合堆的定义,需调整。建立以 h[ 1 ] 为堆顶的正确的最大化堆。数组 h

Page 39: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

39

建堆

70

1

60

240 4

30

5

12

3 8

6

10

7

root[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

70

60

12

40

30

8

10

不合堆的定义,需调整。建立以 h[ 1 ] 为堆顶的正确的最大化堆。数组 h

Page 40: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

40

建堆时间复杂性的分析:

• 时间耗费的代价:建堆的时间耗费 + 排序的时间耗费• 建堆的时间耗费:设树根处于第 1 层,该堆共有 h 层。建堆从第 h-1 层开始进行。只 要知道了每一层的结点数(建的小堆的个数),和每建一个小堆所 需的比较次数,就可以求得建堆的时间耗费。• 建的小堆的性质:第 i 层上小堆的个数 = 第 i 层上结点的个数 = 最多 2i-1

第 i 层上小堆的高度 = h-i+1

建第 i 层上每个小堆最多所需的比较次数 = 2×( h-i)次• 建堆的时间耗费: T(n) <= ∑ 2i-1×(h-i)×2 = ∑ 2i×(h-i) = ∑ 2h-j×j

= 2h ∑ j/2j

注意:即使是 高度为 h 的完全的二叉树,满足以下式子: 2h - 1 <= n <= 2h-1 故: 2h <= 2n

又: ∑ j/2j < 2

所以:建堆的时间复杂性为 4n=O(n) 级

i=h-1i=h-1 j=1

h-1 1 1

j=1

h-1

j=1

10

3040

60 12

7086

2 3

1

74 5

1

2

3=h

Page 41: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

41

建堆• 建立最大化堆

template < class EType> void MaxHeap<EType> :: SiftDown( int j ) { // heap[1], …,heap[n] 为存储堆的数组。 heap[0] 不用。 int MaxSon; // 用于记录大儿子的下标地址。 heap[0] = heap[j]; for ( ; j*2 <= CurrentSize; j = MaxSon) { MaxSon = 2 * j; if ( MaxSon != CurrentSize && heap [MaxSon+1 ] > heap [MaxSon ] ) MaxSon++; if ( heap[MaxSon] > heap[0] ) heap[j] = heap[MaxSon]; else break;}heap [j ] = heap[0];} template < class EType> void MaxHeap<EType> :: BuildHeap( ) { for ( int j= CurrentSize/2; j >0; j-- ) SiftDown(j);}

30 1

70 2

40 4

60 5

12 3

8 6

10 7

j

Page 42: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

42

堆排序

70

60

12

40

30

8

10

values

70

1

60

240 4

30

5

12

3

8

6

root

10

7

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

Page 43: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

43

堆排序values

10

60

12

40

30

8

70 不需再考虑!

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

10

1

60

240 4

30

5

12

3

8

6

root

70

7

Page 44: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

44

堆排序values

60

40

12

10

30

8

70

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

60

1

40

210 4

30

5

12

3

8

6

root

70

7

Page 45: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

45

堆排序

60

40

12

10

30

8

70

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

60

1

40

210 4

30

5

12

3

8

6

root

70

7

Page 46: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

46

堆排序values

8

40

12

10

30

60

70 不需再考虑!

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

8

1

40

210 4

30

5

12

3

60

6

root

70

7

Page 47: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

47

values

40

30

12

10

8

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

40

1

30

210 4

8

5

12

3

60

6

root

70

7

Page 48: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

48

values

40

30

12

10

8

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

40

1

30

210 4

8

5

12

3

60

6

root

70

7

Page 49: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

49

values

堆排序

8

30

12

10

40

60

70 不需再考虑!

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

8

1

30

210 4

40

5

12

3

60

6

root

70

7

Page 50: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

50

values

30

10

12

8

40

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

1

10

2 8 4

40

5

12

3

60

6

root

70

7

Page 51: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

51

values

30

10

12

8

40

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

1

10

2 8 4

40

5

12

3

60

6

root

70

7

Page 52: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

52

values

堆排序

8

10

12

30

40

60

70 不需再考虑!

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

8

1

10

230 4

40

5

12

3

60

6

root

70

7

Page 53: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

53

values

12

10

8

30

40

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

12

1

10

230 4

40

5

8

3

60

6

root

70

7

Page 54: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

54

values

12

10

8

30

40

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

12

1

10

230 4

40

5

8

3

60

6

root

70

7

Page 55: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

55

values

堆排序

不需再考虑!

8

10

12

30

40

60

70

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

8

1

10

230 4

40

5

12

3

60

6

root

70

7

Page 56: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

56

values

10

8

12

30

40

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

10

1

8

230 4

40

5

12

3

60

6

root

70

7

Page 57: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

57

values

10

8

12

30

40

60

70

堆排序[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

30

5

10

7

10

1

8

230 4

40

5

12

3

60

6

root

70

7

Page 58: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

58

数组 h

堆排序

8

10

12

30

40

60

70 不需再考虑!

[ 1 ]

[ 2 ]

[ 3 ]

[ 4 ]

[ 5 ]

[ 6 ]

[ 7 ]

10

230 4

40

5

12

3

60

6

root

70

7

8

1

Page 59: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

59

堆排序template < class EType> void SiftDown( EType a[ ], int j, int Size ) { // a[1], …,a[Size] 为存储堆的数组。 a[0] 不用。注意:本函数用于排序。 Size 为堆的最 // 大下标, j 为当前要建立的最大化堆的堆顶结点的地址。 int MaxSon; // 用于记录大儿子的下标地址。 a[0] = a[j]; for ( ; j*2 <= Size; j = MaxSon) {

MaxSon = 2 * j;if ( MaxSon != Size && a[MaxSon+1 ] > a[MaxSon ] ) MaxSon++;if ( a[MaxSon] > a[0] ) a[j] = a[MaxSon]; else break;

} a[j] = a[0];}template < class EType> void MaxHeapSort( EType a[ ], int Size ) { for ( int j = Size/2; j > 0; j- - ) // a[1], a[2 ], …,a[Size] 为待排序的数组。 a[0] 不用。 SiftDown(a, j, Size); // 将 a[1], a[2 ], …,a[Size]建成最大化堆。 for ( int k = Size; k > 1; k- - ) { Swap( a[1], a[k]); // 交换 a[1] 和 a[k ], 最大元素放在 a[k] 。 SiftDown(a, 1, k-1); // 将 a[1], a[2 ], …,a[k-1] 调整为最大化堆。 }}

Page 60: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

60

堆排序• 时间复杂性的分析:建堆的时间耗费 + 排序的时间耗费• 排序的时间耗费:

结点个数 高度 比较次数最多 j=2 log2 + 1 <= 2× log2

j=3 log3 + 1 <= 2× log3

j=4 log4 + 1 <= 2× log4

j=n-1 log(n-1) + 1 <= 2× log(n-1)

所以: T(n) <= 2( log2 + log3 + …….. + log(n-1) ) = 2log(n-1)!

T(n) = O ( nlogn )

时间复杂性的分析:

10

3040

60 12

7086

2 3

1

74 5

1

2

3=h

Page 61: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

61

堆排序• 堆排序的时间代价分析推导: O ( n logn )

X 轴

Y 轴 求 y=logx 的积分的示意图

2

1

2 3 4

y=logx

1

1 n-1 n

j=2

n-1n

1

 

log(n-1)! = Σ logj ≤ logx dx 不难求出上述积分的值为: nlogn-nloge+loge ≥ nlogn-nloge 。注意到: loge = 1.44 。

Page 62: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

62

堆排序• 最大化堆(最小化堆亦可)用以表示优先队列 常用的基本操作: 1 、 Inset :将具有给定优先数的新结点插入优先队列 ,代价 O(logn) 若分二步: 1 、先找出新结点的插入位置,代价为 O(logn) 2 、通过移动,将新结点插入,代价 O(logn) 总代价仍未改进,仍是 O(logn) 2 、 DeleteMax :删除具有最大优先数的结点, 代价 O(logn) 3 、 Delete :删除任一结点, 代价 O(logn) 4 、 IncreasePriority(DecreasePriority): 增大(或减少)结点的优先数 代价 O(logn) 5 、 Merge : 合并二个优先队列为一个 无法在 O(logn) 内做到 改进:使用最左树

96

5951

83 77 2 3

1

4 5

3931

48 47 6 7

8 9

91114 15

494110 11

292112 13

79316 17

1层2层3层

4层5层

Page 63: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

63

最左树•最左树:是一棵二叉树。结点的 s 值。设二叉树的外部结点 ( 空的儿子结点 ) 的 s 值为 0 ,其他 每个结点的 s 值为左、右儿子结点的 s 值的小者加 1 。如果每个结点的左儿子的 s

值不小于右儿子的 s 值,而且父结点之值大于等于 ( 或小于等于 )儿子结点 ( 如果存在的 话 ) 之值的话,那末这棵二叉树被称之为最左树。

  

 

 

 

  

 

 

 

3

1

111 1

2 2 11

3 2

90

153

2

20 10

75

121

10

13

18

2

3

1 1 11

2

25

68

16 12

24

Page 64: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

64

最左树• 定理:设 x 是最左树的内部结点,那么

1.    以 x 为根的子树的结点的数目至少为 2S(x) – 1 。2.    如果子树 x 有 m 个结点, S(x) 至多为 log2(m+1) 。3.    通过最右路径,从 x 到达外部结点的路径长度为 S(x) 。

•证明: 1. 设 x 所在结点的层次为 0 ,儿子结点的层次为 1 ,以下依次加 1 ,……。 则根据定义, x 的后代中,如果 s 值为 1 ,则该后代的儿子中必有一个为 空。换句话说,由 x 到达最“近”的且 s 值为 1 的后代之前, x 及其后代的 儿子数 2 都为两个。因此,直至第 S(x ) - 1 层没有外部结点,第 S(x ) 层 才有外部结点。所以,结点总数至少为: 1+2+……+2 S(x ) - 1 = 2S(x) -1 个结 点。注意,从第 S(x )层起,开始出现外部结点,同时还可能有内部结 点。 2.由 1. 可知,结点数至少为 2s(x) -1 = m 时, x 的 s 值为 S(x) 。 S(x) 的值至多 为 log(m +1) 。 3. 根据定义,每个内部结点的右儿子的 s 值小于等于左儿子的 s 值,故 通过最右路径,从 x 到达外部结点的路径长度为 S(x) 。很明显,任意结 点的 s 值为本结点到它的度为 0 或 1 的子孙结点的最短路径长度加 1 。

2

3

1 1 11

2

25

68

16 12

24

3

1

111 1

2 2 11

3 2

90

153

2

20 10

75

121

10

13

18

Page 65: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

65

最左树

2

3

1 1 11

2

25

68

16 12

24

3

1

111 1

2 2 11

3 2

90

153

2

20 10

75

121

10

13

18

• 合并最左树示例

11

210

7511

212

24 7 2

• 合并中涉及到的最左树

Page 66: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

66

最左树• 合并过程

                    

1

17

21

17

21

210

5

a、 b、1

17

2

c、

1

212

4

1

210

5

1

17

2

1

212

4

1

210

5

1

17

2

2

3

2 2

25

68

16

1

212

4

1

210

5

1

17

2

d、

f、

e、

 

Page 67: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

67

最左树• 最后得到的最左树

                    

 

                    

1

4

1

111 1

2 2

3

90

153

2

20

121

10

8

302

3

1 1

25

68

16

1

212

4

1

110

5

1

17

2

g、

 

Page 68: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

68

a[0] 用作哨兵。共执行 5 遍操作。每遍操作:先将元素复制内容放入 a[0] ,再将本元素同已排序的序列,从尾开始进行比较。在已排序的序列中寻找自己的位置,进行插入。或者寻找不到,则一直进行到哨兵为止。意味着本元素最小,应该放在 a[1] 。每一遍,排序的序列将增加一个元素。如果序列中有 n 个元素,那么最多进行 n 遍即可。

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

Page 69: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

69

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

3624

j

Page 70: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

70

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

3624

j

Page 71: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

71

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

3624

j

24

Page 72: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

72

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

3610

j

24

Page 73: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

73

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

3610

j

24

Page 74: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

74

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

3610

j

24

Page 75: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

75

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

3610

j

2410

Page 76: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

76

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

36246

j

10

Page 77: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

77

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

36246

j

10

Page 78: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

78

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

36246

j

10

Page 79: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

79

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6 12

3 4 5

36246

j

106

Page 80: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

80

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6

3 4 5

362412

j

106

12

Page 81: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

81

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6

3 4 5

362412

j

106

12

Page 82: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

82

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6

3 4 5

362412

j

106

12

Page 83: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

83

直接插入排序e.g: 36 、 24 、 10 、 6 、 12 存放在 r 数组的下标为 1 至 5 的元素之中,用直接插入法将 其排序。结果仍保存在下标为 1 至 5 的元素之中。

0 1 236 24 10 6

3 4 5

362412

j

106

12

12

Page 84: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

84

直接插入排序0 1 2

10 20 30 403 4 5

10204050

50

30

分析 : 移动、比较次数可作为衡量时间复杂性的标准 正序时:比较次数 ∑ 1 = n-1

i=2 移动次数 2( n-1)

n

逆序时:比较次数 ∑ i = (n+2)(n-1)/2 i=2

移动次数 ∑ (i+1) = (n+4)(n-1)/2 i=2

n

n

Page 85: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

85

直接插入排序0 1 2

36 24 10 63 4 5

362412 106

12

12

template < class EType> void SimpleInsertSort( EType a[ ], int Size ) { int j, q; // a[1], a[2 ], …,a[Size] 为待排序的数组。 a[0] 为哨兵单元。 EType temp=a[0]; for ( j = 2; j <= Size; j++ ) { a[0] = a[j]; for ( q = j; a[0] < a[q-1]; q- -) a[q] =a[q-1]; a[q] = a[0]; } a[0] = temp; // 恢复 a[0] 原来的值,用于快速排序法中。}

程序实现 :

3624106 12j

Page 86: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

86

折半插入排序

template < class EType> void BinaryInsertSort( EType a[ ], int Size ) { int low , high; // a[1], a[2 ], …,a[Size] 为待排序的数组。 a[0] 用哨兵单元。 int j, k, mid; for ( j = 2; j <= Size; j++ ) { a[0]=a[j]; low = 1; high = j -1; // 在 a[ 1 ], …, a[ j-1] 范围内寻找 a[j] 的插入位置。 while ( low <= high ) { mid = ( low + high ) / 2; // 中点下标。 if ( a[0] < a[mid] ) high = mid – 1; // 小于中点,查找左段。 else low = mid +1; // 大于等于中点,查找右段。 } for ( k = j-1; k >= low; - - k ) a[ k+1] = a[ k ]; a[ low ] = a[0]; } }

程序实现 :

36 24 10 6

12362412

high

106

12

12

方法:在已排序的序列中查找下一元素的插入位置,将该元素插入进去,形成更长的排序序列。如: 12 的插入位置为下标 3 。 减少了比较次数,未降低时间复杂性。

jlow

Page 87: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

87

折半插入排序36 24 10 6

12362412

high

106

12

12

方法:在已排序的序列中查找下一元素的插入位置,将该元素插入进去,形成更长的排序序列。如: 12 的插入位置为下标 3 。 减少了比较次数,未降低时间复杂性。

jlow

12362412

high

106 12

jlow

12362412

high

106 12

jlow

m

m

注意 : low 指针总是指向新关键字的下标地址 ,如: 12 的插入位置为 3 。

Page 88: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

88

希尔 (shell) 排序e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4 用 shell 排序的方法进行排序 1 、选定步长序列,如选为 8 、 4 、 2 、 1

2 、针对步长序列进行排序,从最大的步长开始,逐步减少步长,最后一次选择的 的步长肯定为 1 。

步长 8 : 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4

步长 8 : 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4

Page 89: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

89

希尔排序e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4 用 shell 排序的方法进行排序 1 、选定步长序列,如选为 8 、 4 、 2 、 1

2 、针对步长序列进行排序,从最大的步长开始,逐步减少步长,最后一次选择的 的步长肯定为 1 。

步长 8 : 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4

步长 8 : 49 、 4 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 38

步长为 8 的序列的排序结束。

Page 90: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

90

希尔排序e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4 用 shell 排序的方法进行排序 1 、选定步长序列,如选为 8 、 4 、 2 、 1

2 、针对步长序列进行排序,从最大的步长开始,逐步减少步长,最后一次选择的 的步长肯定为 1 。

步长 4 : 49 、 4 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 38

步长 4 : 49 、 4 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 38

Page 91: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

91

希尔排序e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4 用 shell 排序的方法进行排序 1 、选定步长序列,如选为 8 、 4 、 2 、 1

2 、针对步长序列进行排序,从最大的步长开始,逐步减少步长,最后一次选择的 的步长肯定为 1 。

步长 4 : 49 、 4 、 27 、 49 、 55 、 13 、 65 、 97 、 76 、 38

步长 4 : 49 、 4 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 38

Page 92: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

92

希尔排序e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4 用 shell 排序的方法进行排序 1 、选定步长序列,如选为 8 、 4 、 2 、 1

2 、针对步长序列进行排序,从最大的步长开始,逐步减少步长,最后一次选择的 的步长肯定为 1 。

步长 2 : 49 、 4 、 27 、 49 、 55 、 13 、 65 、 97 、 76 、 38

步长 2 : 49 、 4 、 27 、 49 、 55 、 13 、 65 、 97 、 76 、 38

Page 93: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

93

希尔排序e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4 用 shell 排序的方法进行排序 1 、选定步长序列,如选为 8 、 4 、 2 、 1

2 、针对步长序列进行排序,从最大的步长开始,逐步减少步长,最后一次选择的 的步长肯定为 1 。

步长 2 : 27 、 4 、 49 、 13 、 55 、 38 、 65 、 49 、 76 、 97

步长 2 : 49 、 4 、 27 、 49 、 55 、 13 、 65 、 97 、 76 、 38

Page 94: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

94

希尔排序e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 、 55 、 4 用 shell 排序的方法进行排序 1 、选定步长序列,如选为 8 、 4 、 2 、 1

2 、针对步长序列进行排序,从最大的步长开始,逐步减少步长,最后一次选择的 的步长肯定为 1 。

步长 1 : 27 、 4 、 49 、 13 、 55 、 38 、 65 、 49 、 76 、 97

步长 1 : 4 、 13 、 27 、 38 、 49 、 49 、 55 、 65 、 76 、 97最后的排序结果分析 : shell 排序的分析非常困难,原因是何种步长序列最优难以断定。通常认为时间 复杂性为: O( n3/2) .

较好的步长序列:…… 121 、 40 、 13 、 4 、 1; 可由递推公式 Si= 3Si-1 + 1 产生。程序实现 : 类似于直接插入排序的程序。 注意修改步长。

Page 95: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

95

快速排序• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。

0 1 2 3 4 5 6 7 8

49

38

38 65

65 97

97 76

76 13

13 27

27 49

49

highlow

49

界点

Page 96: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

96

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

65 97

97 76

76 13

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 97: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

97

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

65 97

97 76

76 13

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 98: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

98

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

65 97

97 76

76 13

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 99: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

99

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

65 97

97 76

76 13

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 100: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

100

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

76 13

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 101: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

101

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

76 13

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 102: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

102

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

7613

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 103: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

103

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

7613

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 104: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

104

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

7613

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 105: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

105

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

7613

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 106: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

106

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

7613

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 107: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

107

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

49

38

38 65

6597

97 76

7613

13 27

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 108: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

108

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

27

38

38 13

6597

49 76

7613

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 109: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

109

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

27

38

38 13

6597

49 76

7613

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 110: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

110

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

27

38

38 13

6597

49 76

7613

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 111: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

111

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

27

38

38 13

6597

49 76

7613

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 112: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

112

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

27

38

38 13

6597

49 76

7613

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 113: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

113

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

6597

49 76

76 13

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 114: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

114

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

6597

49 76

76 13

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 115: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

115

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

6597

49 76

76 13

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 116: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

116

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 76

76 13

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 117: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

117

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 76

76 13

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 118: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

118

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 76

76 13

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 119: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

119

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 76

76 13

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 120: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

120

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 76

7613

97 65

27 49

49

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 121: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

121

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 49

7613

65 76

2749

97

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 122: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

122

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 49

7613

65 76

2749

97

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 123: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

123

快速排序

e.g: 将序列 49 、 38 、 65 、 97 、 76 、 13 、 27 、 49 用 快速排序的方法进行排序。0 1 2 3 4 5 6 7 8

13

38

27 38

65 97

49 49

7613

65 76

27 49

97

highlow

49

界点

• 原理 : 若序列中有 n 个元素,任选一个关键字作为界点,将序列分成两部分。其 中左半部分的结点的关键字小于等于界点,右半部分的结点的关键字大于等于界 点。然后,对左右两部分分别进行类似的处理,直至排好序为止。

Page 124: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

124

快速排序• 时间复杂性分析 : 考虑平均情况下的时间复杂性。设元素个数为 n ,则所有的排列形式 共有 n! 种。每一个元素都可以充当界点,所以充当界点的情况共计有 n 种。故平均时 间复杂性 T 应为:

T (n) = cn + ∑ [ T (k-1) + T (n-k) ] / n

设: T (0) = T (1) = b

T (n) = cn + 2∑ T (i) / n

nT (n) = cn2 + 2∑ T (i)

(n-1)T (n-1) = c(n-1)2 + 2∑ T (i)

上二式相减的结果为: nT (n) - (n-1)T (n-1) = c(2n-1) + 2T (n-1)

nT (n) = c(2n-1) + (n+1) T (n-1)

K=1

n

n-1

i=0n-1

i=0

i=0n-2

Page 125: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

125

快速排序所以: T (n) / ( n + 1) = c(2n-1) /( n(n+1)) + T (n-1) / n

T (n) / ( n + 1) < = 2c/(n+1) + T (n-1) / n

T (n-1) / n < = 2c/n + T (n-2) / (n-1)

T (2) / 3 < = 2c/3 + T (1) / 2

于是: T (n) < = 2c(n+1)ln(n+1) + b(n+1) / 2

注意:这里使用了一个公式:∑1/k < = ∫ 1/x dx < ln( n + 1)

结论:快速排序在平均情况下的时间复杂性为 O(nlogn) 级或阶的,通常认为是在平 均情况下最佳的排序方法。

K=3

n+1

2 n+1

2

1

1 2 3 4

y=1/x

n n+1

Page 126: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

126

快速排序• 快速排序使用的额外空间 考虑最坏情况,栈的空间为 O(n) 。可以考虑降低到 O(logn) 。

观察以下情况,每次优先处理短的那一段。则空间的使用可以降低到最小。

均匀分段 非均匀分段

在均匀分段的情况下,系统每一次将其中一段的上界、下界的下标压入堆栈,而去处 理另外一段。当处理的一段的元素个数为 1 时,将不必保存另一段的上下界

。这样堆 栈的总的层数为 logn 。在非均匀分段时,由于优先处理短的一段,下降到只有 1 个元 素的段的速度将更快,所以不会超过 logn 。

Page 127: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

127

快速排序• 快速排序的不足和克服方法

1 、在序列差不多排好序时,采用直接插入排序、起泡排序等排序方法。序列的 个数通常取为 10 左右。本书使用了插入排序法用于差不多排好序时。 2 、将递归改成非递归算法。避免进出栈、恢复断点等工作。速度加快。

Page 128: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

128

快速排序• 快速排序的不足和克服方法 3 、最坏情况下 时间复杂性为 O(n2) 级。如:在序列已是正序的情况下。

10 、 20 、 30 、 40 、 50 、 60 、 70 、 80 界点 10 ,共进行 7 次比较。

10 、 20 、 30 、 40 、 50 、 60 、 70 、 80 界点 20 ,共进行 6 次比较。

10 、 20 、 30 、 40 、 50 、 60 、 70 、 80 界点 60 ,共进行 2 次比较。

10 、 20 、 30 、 40 、 50 、 60 、 70 、 80 界点 70 ,共进行 1 次比较。 在最坏情况下:总的比较次数为: (n-1) + (n-2) + …+ 2 + 1 = n2 /2=O(n2)

原因:界点选择不当。改进:随机选取界点或最左、最右、中间三个元素中 的值处于中间的作为界点,通常可以避免最坏情况。

T(n) =1 当 n = 1 时T(n - 1) + (n-1) 当 n > 1 时

Page 129: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

129

快速排序• 快速排序的不足和克服方法原因:界点选择不当。改进:随机选取界点或最左、最右、中间三个元素中 的值处于中间的作为界点,通常可以避免最坏情况。 本书采用的就是吸取了这一改进方法的算法。

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

Page 130: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

130

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

k j

81 67 4 290

k j

Page 131: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

131

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 67 4 290

k j

k

Page 132: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

132

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 67 4 290

k j

k

Page 133: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

133

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 67 4 290

k j

k

Page 134: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

134

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 67 4 920

k j

k

Page 135: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

135

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 67 4 920

k j

k

Page 136: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

136

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 67 4 920

k j

k

Page 137: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

137

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 64 7 920

k j

k

Page 138: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

138

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 64 7 920

k j

k

Page 139: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

139

快速排序· 快速排序 : 本书实现方法的示意图

0 1 2

8 1 9 6 4

3 4 5

1. 初始状态6 7 8

2 7 0

81 67 4 2902. 取中值后

low high

j

81 74 6 920

k j

k

Page 140: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

140

快速排序• 程序实现 :

template < class EType>

void QuickSort( EType arr[ ], int low, int high ) {// arr[low], arr[low+1 ], ……, arr[high] 为待分段的序列。

if ( low + insertnum > high ) SimpleInsertSort( &arr[low], high-low +1); else { int k, j, mid = ( low + high ) / 2;

if ( arr[mid] < arr[low] ) Swap(arr[mid], arr[low]); // 将 arr[low] 、 arr[mid] 、 arr[high]if ( arr[high] < arr[low] ) Swap(arr[high], arr[low]); // 进行排序,找出中间值。if ( arr[high] < arr[mid] ) Swap(arr[mid], arr[high]);

  EType milestone = arr[mid]; Swap( arr[mid], arr[high-1]);for ( k = low, j = high – 1; ; ) // 分成小于等于界点的左段,和大于等于界点的右段。 { while ( arr[++k] < milestone ) ; while ( arr[ - -j ] > milestone ) ;

if (k < j ) Swap(arr[k], arr[j]); else break; }

Swap(arr[k], arr[high-1]); // 将界点放置在正确的位置上。QuickSort(arr, low, k-1); // 对左段进行快速排序。QuickSort(arr, k+1, high); // 对右段进行快速排序。

} }

Page 141: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

141

快速排序• 程序实现 :

const int insertnum = 10;template < class EType> void Swap( EType & x, EType & y ) { EType temp = x; x = y; y = temp; }template < class EType> void SimpleInsertSort( EType a[ ], int Size ) { int j, q; // a[1], a[2 ], …,a[Size] 为待排序的数组。 a[0] 为哨兵单元。 EType temp=a[0]; for ( j = 2; j <= Size; j++ ) { a[0] = a[j]; for ( q = j; a[0] < a[q-1]; q- -) a[q] =a[q-1]; a[q] = a[0]; } a[0] = temp; // 恢复 a[0] 原来的值,用于快速排序法中。 }template < class EType> void QuickSort( EType arr[ ], int n ) { // a[1], a[2 ], …,a[n] 为待排序的数组。 a[0] 不用。 QuickSort( arr, 1, n); }

Page 142: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

142

基数排序• 多关键字排序技术: 多关键字:( K1 ,K2, …… Kt ) ; 例如:关键字 K1 小的结点排在前面。如关键字 K1

相同,则比较关键字 K2 ,关键字 K2 小的结点排在前面,依次类推…… 基数排序实例:假定给定的是 t = 2 位十进制数,存放在数组 B 之中。现要求通过基数排 序法将其排序。

方法:设置 十个口袋,因十进制数分别有数字: 0 , 1 , 2 ,…… 9 ,分别 用 B0 、 B1 、 B2 、 …… B9 进行标识。 执行 j = 1..t ( 这里 t = 2 ) 次循环,每次进行一次分配动作,一次收集动作。

分配:将右起第 j 位数字相同的数放入同一口袋。比如数字为 1 者, 则放入口袋 B1 ,余类推 …… 收集:按 B0 、 B1 、 B2 、 …… B9 的顺序进行收集。

e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数技术进行排序。

Page 143: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

143

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

Page 144: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

144

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

Page 145: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

145

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

Page 146: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

146

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

Page 147: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

147

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

Page 148: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

148

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

Page 149: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

149

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

Page 150: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

150

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

7

Page 151: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

151

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

7

Page 152: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

152

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

7

18

Page 153: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

153

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

7

18

Page 154: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

154

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

7

18

17

Page 155: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

155

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

7

18

17

Page 156: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

156

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。

5

2

9

7

18

17

52

Page 157: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

157

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 5 、 2 、 9 、 7 、 18 、 17 、 52

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋 分配完毕,按照红色 箭头所指的方向进行 收集动作。注意:收集后的序列已经按照右起第一位(个位数字)排好序了。

5

2

9

7

18

17

52

收集后的序列: 2 、 52 、 5 、 7 、 17 、 18 、9 、

Page 158: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

158

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

Page 159: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

159

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

Page 160: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

160

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

Page 161: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

161

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

Page 162: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

162

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

Page 163: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

163

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5

Page 164: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

164

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5

Page 165: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

165

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5 7

Page 166: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

166

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5 7

Page 167: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

167

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5 717

Page 168: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

168

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5 717

Page 169: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

169

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5 717 18

Page 170: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

170

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5 717 18

Page 171: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

171

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋根据 所指向的 数,进行分配动作,将其分配到相应的口 袋。和第一次不同,这次根据右起第二位数字(十位数字)进分配。

2

52

5 717 18

9

Page 172: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

172

基数排序 e.g: B = 5 、 2 、 9 、 7 、 18 、 17 、 52 用基数排序法进行排序。

B = 2 、 52 、 5 、 7 、 17 、 18 、 9 (第一次收集的结果)

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋2

52

5 717 18

9

分配完毕,按照红色 箭头所指的方向进行 第二次收集动作。注意:收集后的序列已经按照右起第一位(个位数字)、右起第二位(十位数字)排好序了。

收集后的序列: 2 、 5 、 7 、 9 、 17 、 18、 52

已是排好序的序列。

Page 173: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

173

基数排序• 空间:采用顺序分配,显然不合适。由于每个口袋都有可能存放所有的待排序的整数。 所以,额外空间的需求为 10n ,太大了。 采用链接分配是合理的。额外空间的需 求为 n ,通常再增加指向每个口袋的首尾指针就可以了。

在一般情况下,设结点的指针场个数 n, 首尾指针共计 2×radix 个 ,总 的空间为 O( n+2×radix ) 。• 时间:上例中每个数计有 t = 2 位,因此执行 t = 2 次分配和收集就可以了。在一般情况 下,每个结点有 d 位关键字,必须执行 t = d 次分配和收集操作。 每次分配的代价: O(n)

每次收集的代价: O( radix )

总的代价为: O( d ×(n + radix))

Page 174: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

174

基数排序

B0

B1

B2

B3

B4

B5

B6

B7

B8

B9

口袋2

52

5 717 18

9

f0 r0

• 首尾指针的使用:

Page 175: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

175

基数排序const int radix = 10; // 如:十进制整数的基为 10 。

const int t = 5; // 整数的最大位数。

typedef struct node { int data ;

int next; // 给出下一个结点的下标地址。 } node;

void BucketSort( node arr[ ], int max ) {

// arr[1], arr[2 ], …,arr[max] 为待排序的整数数组, a[0] 用作头结点。 for ( int j=0; j < max; j++ ) arr[j].next = j + 1; arr[max].next = 0; // 生成静态链表。 RadixSort( arr, max);

}

Page 176: 8.1  概述 8.2  合并排序 8.3  用比较法进行排序的时间下界 8.4  选择排序和堆排序 8.5  插入排序和希尔排序 8.6  快速排序 8.7  基数排序

176

基数排序void RadixSort( node a[ ], int max ) {

int front[radix], tail[radix]; // 口袋的首尾指针。int p, last, j, k, d = 1;for ( j=1; j<= t; j++) { for ( k = 0; k < 10; ++k ) { front[ k ]=0; tail[ k ]=0; } // 口袋的首尾指针置初值。 p = a[0].next; // 头结点 a[0] 给出链中的第一个整数结点的下标地址。

while ( p ) { // 分配过程。 k = a[p].data / d % radix; // 取出右起第 j 位数字,将结点放入口袋 Bk 。

if ( ! tail[k] ) front[ k ] = p; else a[ tail[k] ].next = p; tail[k] = p; p = a[p].next;

} last=0; for ( k = 0; k < radix; ++k) { // 收集过程,从口袋 B0 到最后一个口袋。

if ( tail[k] ) { a[last].next = front[k]; last = tail[k];} a[last].next = 0;

} d *= radix;

} }