Unity3D教程:手游开发常用排序算法 -下

五、堆排序(Heap Sort)

1. 基本思想:

堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。

2. 堆的定义: N个元素的序列K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:

KiK2i Ki K2i+1(1 I [N/2])

Unity3D教程:手游开发常用排序算法

堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均大于等于其孩子结点的关键字。例如序列10,15,56,25,30,70就是一个堆,它对应的完全二叉树如上图所示。这种堆中根结点(称为堆顶)的关键字最小,我们把它称为小根堆。反之,若完全二叉树中任一非叶子结点的关键字均大于等于其孩子的关键字,则称之为大根堆。

3. 排序过程:

堆排序正是利用小根堆(或大根堆)来选取当前无序区中关键字小(或最大)的记录实现排序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无序区调整为一个大根堆,选取关键字最大的堆顶记录,将它和无序区中的最后一个记录交换。这样,正好和直接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。

【示例】:对关键字序列4213912324160588建堆

Unity3D教程:手游开发常用排序算法

Unity3D教程:手游开发常用排序算法

Unity3D教程:手游开发常用排序算法

Unity3D教程:手游开发常用排序算法

01

Procedure Sift(Var R :FileType; I, M : Integer);

02

//在数组R[I..M]中调用R[I],使得以它为完全二叉树构成堆。事先已知其左、右子树(2I+1 <=M)均是堆//

03

Begin

04

X := R[I]; J := 2*I; //J <=M, R[J]R[I]的左孩子//

05

While J <= M Do //若当前被调整结点R[I]有左孩子R[J]//

06

begin

07

If (J < M) And R[J].Key < R[J+1].Key Then

08

J := J + 1 //J指向关键字较大的右孩子//

09

//J指向R[I]的左、右孩子中关键字较大者//

10

If X.Key < R[J].Key Then //孩子结点关键字较大//

11

begin

12

R[I] := R[J]; //R[J]换到双亲位置上//

13

I := J ; J := 2*I //继续以R[J]为当前被调整结点往下层调整//

14

end;

15

Else

16

Exit//调整完毕,退出循环//

17

end

18

R[I] := X;//将最初被调整的结点放入正确位置//

19

End;//Sift//

20

21

Procedure HeapSort(Var R : FileType); //R[1..N]进行堆排序//

22

 Begin

23

  For I := N Div Downto 1 Do //建立初始堆//

24

   Sift(R, I , N)

25

  For I := N Downto 2 do //进行N-1趟排序//

26

   begin

27

    T := R[1]; R[1] := R[I]; R[I] := T;//将当前堆顶记录和堆中最后一个记录交换//

28

    Sift(R, 1, I-1) //R[1..I-1]重成堆//

29

   end

30

 End; //HeapSort//

六、几种排序算法的比较和选择

1. 选取排序方法需要考虑的因素:

(1) 待排序的元素数目n

(2) 元素本身信息量的大小;

(3) 关键字的结构及其分布情况;

(4) 语言工具的条件,辅助空间的大小等。

2. 小结:

(1) n较小(n <= 50),则可以采用直接插入排序或直接选择排序。由于直接插入排序所需的记录移动操作较直接选择排序多,因而当记录本身信息量较大时,用直接选择排序较好。

(2) 若文件的初始状态已按关键字基本有序,则选用直接插入或冒泡排序为宜。

(3) n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序。 快速排序是目前基于比较的内部排序法中被认为是最好的方法。

(4) 在基于比较排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程,由此可以证明:当文件的n个关键字随机分布时,任何借助于“比较”的排序算法,至少需要O(nlog2n)的时间。

(5) 当记录本身信息量较大时,为避免耗费大量时间移动记录,可以用链表作为存储结构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小姑娘很大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值