堆排序算法---属于选择排序

1.堆

  堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

  Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

  即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

  堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。

2.堆排序的思想

  利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

  其基本思想为(大顶堆):

  1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;

  2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];

  3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到 新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

3.操作过程如下:

  1)初始化堆:将R[1..n]构造为堆;

  2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

  因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

4.举例说明堆排序的操作过程

a首先是讲一个无序的序列构建成一个个堆:

 

 b.然后是输出堆顶元素之后,调整剩余元素成为一个新的堆:

5.下面是代码部分:

#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdlib>
#include<cstdio>
const int INF=0X3f3f3f3f;
using namespace std;

typedef struct
{
   int a[100];
   int len;
   void outList(){
           for(int i=1; i<=len; ++i)
               cout<<a[i]<<" ";
           cout<<endl;
   }
}list;
list L;
/**********************************************************************************/

void heapAdjust(int ld, int rd){//堆排序, 排序区间[ld,rd]
    int rc = L.a[ld];
    int cur = ld;
    for(int p = ld*2; p<=rd; p=p*2){
        if(p<rd && L.a[p] > L.a[p+1]) ++p;//取左右子树的最小值
        if(rc < L.a[p]) break;//如果父节点的值比左右子树的值都小,那么已经调整好了,已经是小堆顶了
        L.a[cur] = L.a[p];//否则交换父节点和左右子树最小的子树的值,父节点的值存在rc中,所以只要将最小子树的值赋给父节点就好
        cur = p;
    }
    L.a[cur] = rc;
}

/**********************************************************************************/

int main() {
    int i;
   scanf("%d", &L.len);
   for(i=1; i<=L.len; i++)
     scanf("%d", &L.a[i]);

    for(int i=L.len/2; i>=1; --i)//将整个区间调整成小堆顶,从最后一个非终结点开始
        heapAdjust(i, L.len);

    for(int i=1; i<=L.len; ++i) {
        cout<<L.a[1]<<" ";
        L.a[1] = L.a[L.len-i+1];//将最后一个元素赋给第一个元素
        heapAdjust(1, L.len-i);//重新调整堆
    }
    cout<<endl;
    return 0;
}
时间: 2024-11-01 06:25:46

堆排序算法---属于选择排序的相关文章

我的Java开发学习之旅------&amp;gt;Java经典排序算法之选择排序

一.算法原理 对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置, 接着第二次比较,前面"后一个元素"现变成了"前一个元素",继续跟他的"后一个元素"进行比较如果后面的元素比 他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小的那个数的下标了, 然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整 个数组中最小的数了.然后找

排序算法:选择排序

选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完. 平均时间复杂度:O(n2) 空间复杂度:O(1) (用于交换和记录索引) package cn.hncu; import java.sql.Timestamp; public class selectSort { public static void main(String[] args) { int[] a

Java排序算法_选择排序

选择排序的基本操作就是每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完.算法不稳定,O(1)的额外的空间,比较的时间复杂度为O(n^2),交换的时间复杂度为O(n),并不是自适应的.在大多数情况下都不推荐使用.只有在希望减少交换次数的情况下可以用. 基本思想 n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果: ①初始状态:无序区为R[1..n],有序区为空. ②第1趟排序 在无序区R[1..n]中选出关键字最小的

经典算法:选择排序、插入排序和气泡排序的实现

将要排序的对象分作两部分,一个是一排序的,一个是未排序的,从后面未排序部分选择一个最小 值,并放入前面已排序部分的最后一个.例如: 排序前:70 80 31 37 10 1 48 60 33 80 [1] 80 31 37 10 70 48 60 33 80 选出最小值1 [1 10] 31 37 80 70 48 60 33 80 选出最小值10 [1 10 31] 37 80 70 48 60 33 80 选出最小值31 [1 10 31 33] 80 70 48 60 37 80 ....

常见的五类排序算法图解和实现(选择类:简单选择排序,锦标赛排序,树形选择排序,堆排序)

选择类的排序算法 简单选择排序算法 采用最简单的选择方式,从头到尾扫描待排序列,找一个最小的记录(递增排序),和第一个记录交换位置,再从剩下的记录中继续反复这个过程,直到全部有序. 具体过程: 首先通过 n –1 次关键字比较,从 n 个记录中找出关键字最小的记录,将它与第一个记录交换. 再通过 n –2 次比较,从剩余的 n –1 个记录中找出关键字次小的记录,将它与第二个记录交换. 重复上述操作,共进行 n –1 趟排序后,排序结束. 如图   过程图解 令 k=i:j = i + 1: 目

C语言 选择排序算法详解及实现代码_C 语言

选择排序是排序算法的一种,这里以从小到大排序为例进行讲解. 基本思想及举例说明 选择排序(从小到大)的基本思想是,首先,选出最小的数,放在第一个位置:然后,选出第二小的数,放在第二个位置:以此类推,直到所有的数从小到大排序. 在实现上,我们通常是先确定第i小的数所在的位置,然后,将其与第i个数进行交换. 下面,以对 3  2  4  1 进行选择排序说明排序过程,使用min_index 记录当前最小的数所在的位置. 第1轮 排序过程 (寻找第1小的数所在的位置) 3  2  4  1(最初, m

《算法基础:打开算法之门》一3.2 选择排序

3.2 选择排序 现在让我们将注意力转向排序:重排数组中的所有元素--也称为重排数组--以便每个元素小于或者等于它的后继.我们要看到的第一种排序算法是选择排序,这是我能想到的最简单的算法,在设计一个排序算法时,我最先能想到的就是选择排序,虽然它远远不是最快的算法. 下面我们用依据作者名字对书架上的书排序这个例子来说明选择排序是如何运行的.从左向右查找整个书架,并且找到作者名字最先在字母表中出现的书籍.假定这本排序在字母表中最前的书籍是由Louisa May Alcott所写的(如果书架上包含由该

Java对数组实现选择排序算法的实例详解_java

一. 算法描述    选择排序:比如在一个长度为N的无序数组中,在第一趟遍历N个数据,找出其中最小的数值与第一个元素交换,第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个元素交换......第N-1趟遍历剩下的2个数据,找出其中最小的数值与第N-1个元素交换,至此选择排序完成. 以下面5个无序的数据为例: 56 12 80 91 20(文中仅细化了第一趟的选择过程) 第1趟:12 56 80 91 20 第2趟:12 20 80 91 56 第3趟:12 20 56 91 80 第4趟:

java实现选择排序算法_java

java实现选择排序算法 public static void selectSort(int[] array) { for (int i = 0; i < array.length - 1; i++) { int min = i; for (int j = i + 1; j < array.length; j++) { if (array[j] < array[min]) { min = j; } } Sort.swap(array, i, min);//交换i和min } } 选择排序