选择排序——堆排序

思路

有n个元素的序列r[1..n]

满足第k个元素不小于2k与2k+1

或者不大于2k与2k+1。

很明显,堆可以看成完全二叉树的线性序列

由以上性质可知,堆-二叉树的树根节点 就是序列中最大或者最小的元素(r[1])

那么我们把一个序列变成堆,就可以得到最值关键字。根选择排序思想一致,找出最大或最小关键字。

步骤:

序列r[1..n] 变成堆,假设是大根堆,交换r[1]与r[n];

序列r[1..n-1]变成堆,交换r[1]与r[n-1];

重复上述步骤,直到交换r[1]与r[2] ,即n-1次变成堆的操作。

最终变成一个增序序列。

如何把无序序列变成堆?

调整堆

如果有r[s+1..m]为堆,r[s..m]不为堆

那么就要把r[s+1..m]变成以r[s]为根节点的堆r[s..m]

算法步骤:

从r[2s]与r[2s+1]中选择关键字较大者(大根堆),假设r[2s]较大

比较r[s]与r[2s];

r[s]>=r[2s] ,不需要调整

r[s]<r[2s],交换两者。因为以r[2s+1]为根的子树仍是堆,故不需要调整。

令s=2s,重复上述过程,直到r[s]为根节点。

代码如下:

struct Sqlist {

int r[100];

int len;

};

void HeapAdjust(Sqlist& L,int s,int m)

{

int rc = L.r[s];

for (int j = 2 * s; j <= m; j *= 2)

{

if (j < m && L.r[j] < L.r[j + 1])++j;//较大关键字

if (rc >=L.r[j])break;//不需要调整

L.r[s] = L.r[j]; s = j;//r[s]替换

}

L.r[s] = rc;//叶节点的值更新为rc

}

建初堆

首先思考在完全二叉树中最小堆是?

很明显是叶节点。那么以叶节点为孩子节点的最小子树,只有根节点不是满足堆性质的。

算法步骤:

若序列有n个节点,那么第[n/2]个节点就是最后一个非终端节点(非叶节点)。从[n/2]个节点开始,[n/2]-1,[n/2]-2,,,1.依次调整堆,最后整个序列都被调整为堆

代码如下:

void Creatheap(Sqlist& L)

{

int n = L.len;

for (int i = n / 2; i > 0; i--)

{

HeapAdjust(L, i, n);

}


}

堆排序代码:

void HeapSort(Sqlist& L)

{

Creatheap(L);

for (int i = L.len; i > 1; i--)

{

int x = L.r[1];

L.r[1] = L.r[i];

L.r[i] = x;

HeapAdjust(L, 1, i - 1);

}

}

实验结果:

感谢您的观看,后续会出归并排序,希尔,快速排序。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值