排序算法:堆排序

堆排序

1. 堆:
    1. 一种完全二叉树。
    2. 每个结点的值都大于或等于其左右子结点的值,大顶堆。
    3. 小顶堆同理。
2. 是简单选择排序的一种改进:把每次比较的结果用堆来保存起来。
3. 堆排序(大顶堆):
    1. 将待排序列构造成一个大顶堆。
    2. 将堆顶和待排序列最后一个元素交换,也就是保存起来。
    3. 将剩余的序列(去除最后一个元素)重新构造成一个堆。
    4. 重复23 。

4. 待排序列构造初始大顶堆:
    1. 设序列长度length,已经构造好最初的完全二叉树,无序。
    2. 从最下层最右边的非叶子结点开始向左向上。
    3. 二叉树的性质:根节点从序号1开始,设某个结点的序号为k,则其左子树的序号是2k,右子树的序号是2k+1。最下层最右边的非叶子结点就是length/2取整。
    4. 从第【length/2取整】个结点开始,向根节点(序号为1)开始 逐个调整每个子树的三个结点的顺序,让其成为大顶堆。
    5. 交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整
    6. 最后调整到根节点时候,整个树就是一个大顶堆。

复杂度

1. 构建堆:O(n)
2. 重建堆:O(nlogn),调整的是根节点的左子树或者右子树,而调整的次数也就是该二叉树目前的深度,也就是【log2n】+1,每次都要调整,一共调整n-1次,所以复杂度就是O(nlogn)。
3. 总复杂度:O(nlogn)
4. 对原始记录的排序状态不敏感,反正都要构造初始堆。
5. 不稳定。
6. 构建堆需要多次比较,待排序列个数较少的情况不适合。

图示

代码实现

//构建大顶堆的调整算法
void sift(int r[],int k,int m)
{
    int i = k;
    int j = 2*k;
    while (j<=m)
    {
        if (j<m && r[j]<r[j+1])
        {
            //j指向较大的孩子结点
            j = j + 1;
        }
        if (r[i]<=r[j])
        {
            int temp = r[i];
            r[i] = r[j];
            r[j] = temp;
            //根节点的调整会影响孩子结点,所以一直调整到m
            i = j;
        j = 2*i;
        }
        else
        {
            break;
        }

    }
}
//堆排序
void HeapSort(int r[ ], int n)
{
    int i;
    for (i=n/2; i>=1; i--)       //初始建堆,从最后一个非终端结点至根结点
    {
    sift(r, i, n) ;
    }
    for (i=1; i<n; i++)        //重复执行移走堆顶及重建堆的操作
    {
        int temp = r[1];
        r[1] = r[n-i+1];
        r[n-i+1] = temp;
        sift(r, 1, n-i);
    }
}

用例:

int a[] = {0,36,30,18,40,32,45,22,50};
    int i ;
    for (i = 1;i<9;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;

    HeapSort(a,8);
    for (i = 1;i<9;i++)
    {
        cout<<a[i]<<" ";
    }
时间: 2024-11-07 03:49:24

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

经典排序算法 - 堆排序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-

经典排序算法

经典排序算法(via  kkun) 经典排序算法,以下文章参考了大量网上的资料,大部分都给出了出处 这一系列重点在理解,所以例子什么的都是最简单的情况,难免失误之处,多指教 大多数排序算法都给出了每一步的状态,以方便初学者更容易理解,通俗易懂,部分难以理解的排序算法则给出了大量的图示,也算是一个特色吧 经典排序算法 - 快速排序Quick sort 经典排序算法 - 桶排序Bucket sort 经典排序算法 -  插入排序Insertion sort 经典排序算法 - 基数排序Radix so