数据结构——堆(堆排序)

简介: 数据结构——堆(堆排序)

1.堆

堆的逻辑结构是一颗完全二叉树

堆的物理结构是一个顺序表

通过下标去实现父子节点关系

leftchild=parent*2+1
rightchild=parent*2+2
parent=(child-1)/2;

就类似于下图

image.png

image.png

2.堆的两个特性

大堆:所有父亲大于等于孩子

小堆:所有父亲小于等于孩子

结构性:用数组表示的完全二叉树

有序性:任意结点的关键字是其子树所有结点的最大值(或最小值)

最大堆”也称“大堆顶”:最大值

最小堆”也称“小堆顶”:最小值

image.png

3 .向下调整算法(以大堆为例)

//向下调整算法(左右子树必须是大堆)
void AdjustDown(int*a,int n,int root)
{
    int parent=root;
    int child=parent*2+1;
    while(child<n)
    {
        if( child+1<n && a[child+1]>a[child])
        {
            child+=1;
        }
        if(a[child]>a[parent])
        {
            Swap(&a[child],&a[parent]);
            parent=child;
            child=parent*2+1;
        }
        else
        {
            break;
        }
    }
}
那么左右子树不是小堆,就不能直接使用向下调整算法了,怎么办
可以倒着从最后一颗子树开始调
从最后一个非叶子结点开始调,最后一个非叶子节点的下标是(n-1-1)/2                      
    for(i=(n-2)/2;i>=0;i--)
    {
        AdjustDown(arr,n,i);
    }

2.排序

如果我们要给数组排升续,那么我们需要建大堆

每一次向下调整都可以找出一个最大的数放在第一个位置,

我们可以把第一个和最后一个交换,然后把最后一个数(也就是找出的那个最大的数)不看作

前n-1个数,继续向下调整,选出次大的数,再跟倒数第二个位置交换,后面过程以此类推。

到最后就可以完成排序。

image.png

动图点此查看

image.png

 //建堆O(n)
 for(i=(n-2)/2;i>=0;i--)
 {
     AdjustDown(arr,n,i);
 }
 //排升序,建大堆
 int end=n-1;
 while(end>0)
 {
     Swap(&arr[0],&arr[end]);
     AdjustDown(arr,end,0);
      end--;
 }

4.完整代码

//交换两个数函数的分装
void Swap(int*x,int*y)
{
    int temp=*x;
    *x=*y;
    *y=temp;
}
//向下调整算法(左右子树必须是大堆)
void AdjustDown(int*a,int n,int root)
{
    int parent=root;
    int child=parent*2+1;
    while(child<n)
    {
        if( child+1<n && a[child+1]>a[child])
        {
            child+=1;
        }
        if(a[child]>a[parent])
        {
            Swap(&a[child],&a[parent]);
            parent=child;
            child=parent*2+1;
        }
        else
        {
            break;
        }
    }
}
#include<stdio.h>
int main()
{
    int i=0;
    int arr[]={10,9,8,7,6,5,4,3,2,1};
    int n=sizeof(arr)/sizeof(arr[0]);
    //建堆O(n)
    for(i=(n-2)/2;i>=0;i--)
    {
        AdjustDown(arr,n,i);
    }
    //排升序,建大堆
    int end=n-1;
    while(end>0)
    {
        Swap(&arr[0],&arr[end]);
        end--;
        AdjustDown(arr,end,0);
    }
    for(i=0;i<n;i++)
    {
        printf("%d ",arr[i]);
    }
    return 0;
}

5.时间复杂度的计算

用n表示元素个数

向下调整算法 ,最多向下调整高度(二叉树高度)次。

h=log(n);

所以一次向下调整的时间复杂度是log(n)

建堆的时间复杂度

T(n)=1*(h-1)+ 2* (h-2)+ 4* (h-3)+…2^(h-2)


T(n)= -h+2^h-1


建堆的时间复杂度就约等于O(N)


整体的时间复杂度O(N*logN)


相关文章
|
3天前
|
存储 Java
【数据结构】优先级队列(堆)从实现到应用详解
本文介绍了优先级队列的概念及其底层数据结构——堆。优先级队列根据元素的优先级而非插入顺序进行出队操作。JDK1.8中的`PriorityQueue`使用堆实现,堆分为大根堆和小根堆。大根堆中每个节点的值都不小于其子节点的值,小根堆则相反。文章详细讲解了如何通过数组模拟实现堆,并提供了创建、插入、删除以及获取堆顶元素的具体步骤。此外,还介绍了堆排序及解决Top K问题的应用,并展示了Java中`PriorityQueue`的基本用法和注意事项。
18 5
【数据结构】优先级队列(堆)从实现到应用详解
|
1月前
|
存储 算法
【数据结构】堆
【数据结构】堆
|
1月前
|
存储 算法 Linux
【数据结构】树、二叉树与堆(长期维护)(1)
【数据结构】树、二叉树与堆(长期维护)(1)
|
1月前
|
算法
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
|
19天前
|
存储 程序员 C语言
堆和栈之间有什么区别
【9月更文挑战第1天】堆和栈之间有什么区别
89 0
|
30天前
|
算法 机器人
【数据结构】什么是堆
【数据结构】什么是堆
31 0
|
1月前
|
搜索推荐 算法
【初阶数据结构篇】插入、希尔、选择、堆排序介绍(上篇)
堆排序(Heapsort)是指利⽤堆积树(堆)这种数据结构所设计的⼀种排序算法,它是选择排序的⼀ 种。它是通过堆来进⾏选择数据。需要注意的是排升序要建⼤堆,排降序建⼩堆。
|
1月前
|
算法
【初阶数据结构篇】堆的应用(堆排序与Top-K问题)
即求数据结合中前K个最⼤的元素或者最⼩的元素,⼀般情况下数据量都⽐较⼤。
|
1月前
|
存储 算法 测试技术
【初阶数据结构篇】实现顺序结构二叉树(堆的实现方法)
注意传过去的参数是插入的位置,即插入前的size,在调整完后再将size++
|
1月前
|
存储
全局变量和局部变量在堆和栈的区别
全局变量和局部变量在堆和栈的区别
117 0