排序算法: 堆排序法

一,使用堆排序法之前,需要了解堆的特性:

1,堆一般都用数组的方式来存储,堆分为“最大堆”和“最小堆”;

2,以“最大堆”为例:

 (1)一个节点最多有两个子节点,即左右节点,每个节点都是一个堆;

 (2)父节点的值不小于子节点的值;

 (3)一个i节点其父节点为(i-1)/2,左节点(2*i+1),右节点(2*i+2)

一个最大堆例子:

数组 int a[]:

83 78 81 48 17 27

二,将一个数组形成堆(以最大堆为例)

数组a[]:

27 48 81 78 17 83

形成最大堆思路:

(1)len=6为数组长度, i=len/2=3,从第i个节点开始,将第i个节点形成最大堆,直至i<0,即到根节点;

(2)在第i个节点中,选出子节点(2*i+1)(2*i+2)中的最大值;

(3)父节点和子节点最大值比较,如果子节点值更大,则位置互换,否则不变;

(4)重复前三个步骤

图示过程:

注:本例len=6,i=len/2=3,由于a[3]=78无子节点,所以图例从a[2]开始展示。

实现代码:

/**************************************************************************************
 *  Description: 形成一个最大堆
 *   Input Args: a代表数组指针,j为要排序的数索引,num为数据长度
 *  Output Args: 得到一个最大堆
 * Return Value: 1
 *************************************************************************************/
int slipdown (int a[], int j, int num)
{
    int temp = a[j];
    int i;

    for(i=(2*j+1); i<=num; i=(2*j+1))
    {
        /* 保证左右子节点存在前提,找出最大值 */
        if(i+1<num && a[i]<a[i+1])
            i++;

        /* 如果子节点更大,移到父节点  */
        if(i<num && a[i]>temp)
            a[j]=a[i];
        else
            break;

     /* 转入子节点 */
        j=i;
    }

    a[j]=temp;

    return 0;
} /* ----- End of slipdown()  ----- */

三,堆排序

堆建好之后堆第0个数据是堆中最大的数据,将第0个数据和最后一个数据交换之后,再次形成最大堆,直到最后堆剩余一个数。此时,得到一个由小到大的数组。如果需要得到由大到小数组,可以形成最小堆。

实现代码:

/**************************************************************************************
* Description : 打印函数
* Input Args  : a为数组指针; num为数组长度; str为传入需要指针,指向需要打印字符串
* Output Args :
* Return Value:
*************************************************************************************/

void print(int *a, int num, char *str)
{
    int i = 0;

    if(num==0)
        return;

    printf("show the data %s structure:\n", str);
    for(i=0; i<num; i++)
    {
        printf("%3d ", *(a+i));
    }

    printf("\n");
}/* ----- End of print()  ----- */

/**************************************************************************************
* Description:
* Input Args:
* Output Args:
* Return Value:
*************************************************************************************/

int swap (int *a, int *b)
{
  int temp;


temp = *a;
*a = *b;
*b = temp;


return 0;
} /* ----- End of swap() ----- */



/**************************************************************************************
 *  Description: 堆排序法
 *   Input Args: a为数组指针, num为数组长度
 *  Output Args:
 * Return Value:
 *************************************************************************************/
int heap_sort (int *a, int num)
{
    int i;

    if(num==0)
        return -1;

    /* make a large heap top */
    for(i=num/2; i>=0; i--)
        slipdown(a, i, num);
    print(a, num, "heap");

  /* The heap sort */
    for(i=num-1; i>=1; i--)
    {
        swap(&a[i], &a[0]);
        slipdown(a, 0, i);
    }

    return 0;
} /* ----- End of heap_sort()  ----- */

参考链接:

维基百科排序算法大全:http://zh.wikipedia.org/wiki/排序算法

白话经典算法系列之七 堆与堆排序:http://blog.csdn.net/morewindows/article/details/6709644/

时间: 2024-10-07 00:37:58

排序算法: 堆排序法的相关文章

经典排序算法 - 堆排序Heap sort

经典排序算法 - 堆排序Heap sort 堆排序有点小复杂,分成三块 第一块,什么是堆,什么是最大堆 第二块,怎么将堆调整为最大堆,这部分是重点 第三块,堆排序介绍 第一块,什么是堆,什么是最大堆 什么是堆 这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构. 堆可以视为一棵完全的二叉树,完全二叉树的一个"优秀"的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素. 数组与堆之间的关系 二叉堆一般分为两种:最大堆和最小堆. 什么

Java排序算法 - 堆排序的代码

把内容过程中比较重要的一些内容片段做个备份,如下的资料是关于Java排序算法 - 堆排序的内容. import java.util.Arrays; public class HeapSort { int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51}; public HeapSort(){ heapSort(a); } public void heapSort(int[

[算法学习笔记]排序算法——堆排序

堆排序 堆排序(heapsort)也是一种相对高效的排序方法,堆排序的时间复杂度为O(n lgn),同时堆排序使用了一种名为堆的数据结构进行管理. 二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树.二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆. 如上图显示,(a)是一个二叉堆(最大堆), (b)是这个二叉堆在数组中的存储形式. 通过给个一个节点的下标i, 很容易计算出其父节点,左右子节点的的下标,为了方便,

经典排序算法——堆排序

对于一个int数组,请编写一个堆排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2,2,3,3,5] class HeapSort { public: int* heapSort(int* A, int n) { BuildMaxHeap(A, n);//首先将数组A构建成大顶堆 for (int i = n - 1; i >= 1; i--) { swap(A[0],A[i]);//将堆顶最大值与未排序的最

排序算法-堆排序

堆排序算法是建立在堆这种数据结构的基础上,其实堆听着很高端,其实很简单,就是一个二叉树,但是又特殊条件,就是其父节点比孩子节点都大(或都小)的堆称为最大堆(最小堆),瞬间感觉很简单了,最简单的保存方法就是直接用数组来保存. 给出一组数,我们要使用堆排序,首先需要建堆,但是这一组数首先肯定是不满足上面堆的性质的,所以我们需要调整,让他满足堆得性质,变成一个堆,怎么调整呢?拿最大堆来说,就是对于一个节点,我们判断其孩子是否有比父亲节点大的,有的话,交换这两个值,这样父亲就比孩子都大了,当然交换完了之

八大排序算法——堆排序(动图演示 思路分析 实例代码java 复杂度分析)

一.动图演示 二.思路分析 先来了解下堆的相关概念:堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆:或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆.如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]   小顶堆:arr[i]

排序算法——堆排序

堆排序 ①了解二叉堆的定义 ②一般用数组表示堆 注意逻辑存储结构和实际存储结构 ③i节点的 父节点(i-1)/2 子节点 左2*i+1 右2*i+2 ④注意每种操作的思想 ⑤一般数组要堆化操作后再进行堆排序 代码实现 /*本栗子是最小堆*//*从第i个节开始调整*/ void MinHeapDown(int a[],int i,int n) { int j=0,temp=0; temp = a[i]; j=2*i+1;/*i节点的左孩子*/ while(j < n) { if(j+1<n &a

Java排序算法——堆排序

堆排序 package sort; public class Heap_Sort { public static void main(String[] args) { // TODO 自动生成的方法存根 Heap_Sort qs = new Heap_Sort(); int[] Arr = {10,9,8,7,6,5,4,3,2,1}; qs.heapSort(Arr); for(int i=0;i<Arr.length;i++){ System.out.println(Arr[i]); } }

JavaScript排序算法——堆排序

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

java几种常见的排序算法总结

[java] view plain copy /*************几种常见的排序算法总结***************************/ package paixu; public class PaiXu { final int MAX=20; int num[]=new int[MAX]; { System.out.print("生成的随机数组是:"); for(int i=0;i<20;i++){ num[i]=(int)(Math.random()*100)