zoukankan      html  css  js  c++  java
  • 排序算法(3)-堆排序

    堆排序的时间复杂度为O(nlgn),具空间原址性,主要特点是引入了堆的数据结构来信息管理。

    一、堆的概念

    了解堆的概念前了解几个相关的概念

    1.相关概念:

    image  image

    满二叉树,每个结点为叶节点或者度为2. 完全二叉树,叶节点都在同一节,每个内部结点的度都为2.

    image

    结点的高度:结点到叶的简单路径的边数

    结点的层次:根节点到节点的路径长度
    树的高度:根节点的高度

    二叉树的一些性质: 高度为d的二叉树结点数最多为 image 。结点数位n的二叉树高度至少为lgn向下取整。

    2.堆(主要讨论最大堆,最小堆类似):

    堆是一个接近完全的二叉树主要有两个特点(1),除了最后一个层次,其他层次都是完成,最后一个层次是从左到右充满的。(2),最大堆对于任意结点,符合父节点大于子节点Parent(x) ≥ x。

    堆是怎么存储的呢?一个堆可以存储成一个数组。

    image image

    如图:右边为一堆,堆顶为a[1],i节点左孩子序号为2i;右孩子为2i+1;父节点为image 。其中image 为叶节点(叶节点数跟非叶几点相等),

    二、堆的几个基本过程

    1.max_heapify

    这个过程主要是为了维护最大堆性质,使父节点大于左右子树节点,是一个递归的。这里要注意的一个地方是前提必须保证左右子树都已经满足最大堆的性质

    imageimage image  image image

    节点跟左右节点比较,记录最大节点的序号,若最大节点不是当前节点,将最大和当前节点交换,然后递归调用这个过程对被交换的子节点进行,直到到叶节点。程序

    void max_heapify(int a[],int i,int heapsize)
    {
        int l=2*i+1, r=2*i+2,largest=i;
        if (l<heapsize&&a[l]>a[i])
            largest=l;
        else largest=i;
        if (r<heapsize&&a[r]>a[largest])
            largest=r;
        if (largest!=i)
        {
            int temp=a[largest];
            a[largest]=a[i];
            a[i]=temp;
            max_heapify(a,largest,heapsize);
        }    
    }

    堆的高度heapsize由程序插入,l,r,定义左右节点的序号(数组序号从0开始,所以跟前面有些不同),两个if判断最大的在哪,然后判断最大是否为当前,不是,交换值。

    运行时间,最坏就是沿着树根一直下到叶节点,每次都要比较2次,树的高度h=lgn,所以运行时间为O(lgn)。

    2.build_max_heap

    这个过程是输入一个序列,在上面构建一个最大堆,根据堆的性质image 都是叶节点满足堆的性质,所以只需要从1..image 间维护最大堆的性质就可以。

    image

    void build_maxheap(int a[],int heapsize)
    {   
        
        for (int i=heapsize/2-1;i>=0;i--)
        {
            max_heapify(a,i,heapsize);
        }
    }

    是从heapsize/2…1。不是从1...heapsize/2。这是max_heapify的函数决定的,因为对某个节点维护最大堆的性质时,必须保证左右子树满足最大堆的性质,这样才能达到这个树具堆的性质。所以要至底向上一步步维护,使这个树有序。

    3.heap_sort

    堆排序,有了前面的基础,我们能够在一个序列上构建最大堆,根节点是序列的最大值,取出最大值与最后一个值交换,从树种删去这一点,然后维护最大堆性质,使最大值到根节点,不断循环。

    image

    程序:

    void heap_sort(int a[],int heapsize)
    {  
         build_maxheap(a,heapsize);
        for (int i=heapsize-1;i>=1;i--)
        {
            int temp=a[0];
            a[0]=a[i];
            a[i]=temp;
            max_heapify(a,0,i);
        }
    }

    整个程序

    #include <iostream>
    const int len=8;
    using namespace std;
    void max_heapify(int a[],int i,int heapsize)
    {
        int l=2*i+1, r=2*i+2,largest=i;
        if (l<heapsize&&a[l]>a[i])
            largest=l;
        else largest=i;
        if (r<heapsize&&a[r]>a[largest])
            largest=r;
        if (largest!=i)
        {
            int temp=a[largest];
            a[largest]=a[i];
            a[i]=temp;
            max_heapify(a,largest,heapsize);
        }    
    }
    void build_maxheap(int a[],int heapsize)
    {   
        
        for (int i=heapsize/2-1;i>=0;i--)
        {
            max_heapify(a,i,heapsize);
        }
    
    
    }
    void heap_sort(int a[],int heapsize)
    {  
        build_maxheap(a,heapsize);
        for (int i=heapsize-1;i>=1;i--)
        {
            int temp=a[0];
            a[0]=a[i];
            a[i]=temp;
            max_heapify(a,0,i);
        }
    
    
    }
    int main()
    {  
        int a[len]={2,8,7,1,3,5,6,4};
        heap_sort(a,8);
    
        for(int i=0;i<len;i++) cout<<a[i]<<" ";
        cout<<endl;
    } //main end
  • 相关阅读:
    ubuntu 安装docker
    docker 版本与查看某个容器详情信息
    linux namespace 分为有名和无名两种,默认情况下都是有名的
    查看centos 版本信息
    centos7 一键安装openstack 方法
    centos8 安装openstack (失败告终),参见centos7安装
    Windows7 安装docker工具的方法
    网络架构--防火墙双机热备(主备、负载均衡)
    ubuntu server 无线网口配置
    ubuntu server 18.04 单机安装openstack
  • 原文地址:https://www.cnblogs.com/dawnminghuang/p/3884596.html
Copyright © 2011-2022 走看看