选择类排序

选择类排序的基本思想是每一趟在n-(i-1)个待排序的记录中选取一个关键字最小的记录作为有序序列中的第i个记录。常用的选择类排序法有简单选择排序和堆排序。

1.简单选择排序

简单选择排序是对选择类排序基本思想的直接实现。在第一趟排序中,从第一个记录开始在待排序的n个记录中选择一个最小的记录,并和第一个记录作交换;在第二趟排序中,从第二个记录开始从待排序的n-1个记录中选择一个最小的记录,并和第二个记录做交换。依次类推,第i趟排序过程即从第i个元素开始在待排序的n-(i-1)个元素中选择一个最小的记录,并和第i个记录作交换。

void selectSort(int *r, int length)
{
    int i, j, k, n;
    n = length;
    for ( i = 1; i <= n - 1; i++) {
        k = i;
        for ( j = i + 1; j <= n; j++)
            if (r[j] < r[k])
                k = j;
        if ( k != i) {
            r[0] = r[i];
            r[i] = r[k];
            r[k] = r[0];
        }
    output(r, length);
    }
}


在具体实现时,外部循环用来控制总的排序趟数,而内部循环用于在剩余待排序记录中挑选一个最小的记录。在每一趟排序中,使用k记录最小记录的索引。

2.堆排序

堆排序将一维的待排序记录按照完全二叉树的形式进行组织,并利用完全二叉树中父节点和孩子节点之间的关系来选择记录,最终达到排序的目的。堆排序只是利用了完全二叉树的特性,待排序记录仍然采用一维数组进行存储,而非采用树的存储结构。 堆排序的算法思想是将待排序的记录r[1,n]看作是一棵完全二叉树,将记录1作为完全二叉树的根节点,记录中的其他元素依次逐层从左至右顺序排序。首先将该完全二叉树调整为大根堆(最终排列成递减序列),也就是创建堆的过程;接着,将根元素从二叉树中移除并作为有序记录集合中的第一个元素,同时再次调整该二叉树让其形成另一个大根堆。不断重复上述过程直到该完全二叉树为空。实现代码如下:

void heapSort(int *r, int length)
{
    int i, n;
    int t;
    create_heap(r, length);
    n = length;
    for ( i = n; i >= 2; i--) {
        t = r[1];
        r[1] = r[i];
        r[i]= t;
        adjust_heap(r, 1, i - 1);
        output(r, length);
    }
}


在具体的实现堆排序时,通常是将堆顶元素和堆尾元素进行交换,再次调整剩余待排序的元素形成堆。第i趟排序是将堆顶元素r[1]和堆尾元素r[n-i+1]进行交换,此时序列r中后i个元素是有序的。

堆的创建就是自底向上逐层调整该完全二叉树的子树。对于n个元素的记录来说,先将以第n/2个元素为根的子树调整为大根堆,再将以n/2-1个元素为根的子树调整为大根堆,按照逐层自底向上的顺序,直到根节点。

void create_heap(int *r, int length)
{
    int i, n;
    n = length;
    for ( i = n / 2; i >= 1; i--)
        adjust_heap(r, i, n);
}

整个堆排序的核心算法是调整堆,其中r[k,m]是一个以k元素为根的完全二叉树,该算法将此二叉树调整为堆。具体实现时,用r[0]备份当前二叉树的根元素,用j表示i元素的左孩子。算法中使用循环不断将二叉树调整为堆,它首先确定i节点的两个孩子中的较大值,再进一步判断是否需要与根节点进行交换。如果根节点大于i节点较大的那个孩子节点j,整个调整过程结束,因为此时该二叉树就是一个堆。否则将这个较大值的孩子j移到节点i处,接下来以j为根节点继续如上考察它的两个孩子节点的大小。

void adjust_heap(int *r, int k, int m)
{
    int i, j, t;
    int finished;
    r[0] = r[k];
    i = k;
    j = 2 * i;
    finished = 0;
    while (j <= m && !finished) {
        if (j < m && r[j] < r[j + 1])
            j++;
        if (r[0] >= r[j])
            finished = 1;
        else {
            r[i] = r[j];
            i = j;
            j = 2 * i;
        }
    }
    r[i] = r[0];
}

整个调整堆的过程是由根节点逐步向下筛选的过程。


http://edsionte.com/techblog/archives/3817

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值