美文网首页
堆排序(一)堆排序的实现以及实现细节

堆排序(一)堆排序的实现以及实现细节

作者: chengcongyue | 来源:发表于2019-04-09 23:02 被阅读0次

前言

堆的数据结构我们在这里不详述,堆排序总的来说一共就两步,即建立一个队使用的方式的HeapInsert和当堆顶离开时,如何维护这个堆,Heapify.
对于heap最基础的也是十分重要的一点就是父与子的关系,如下图

图片.png
如图我们可以知道
父亲的下标=(子下标-1)/2
左孩子的下标=2父亲的下标+1
右孩子的下标=2
父亲的下标+2
根据上面的三个关系,我们就可以分别完成heapInsert和Heapify的方法
heapInsert的含义
for(int i=0;i<arr.length;i++)
{
heapInsert(arr,i);//以i为起点,开始向回比较,每次比较的都是(index-1)/2的关系
}

然后我们来看一下HeapInsert的方法,十分的简单

//参数,就是将arr[]传入
public static void heapInsert(int[] arr,int index)
{
     while(arr[index]>arr[(index-1)/2])
     {
             swap(arr,index,(index-1)/2);
             index=(index-1)/2;
     }
}

然后用for循环遍历它,让数组的每一个arr[]元素,都依次的向上"爬"
这个就是HeapInsert的方法

heapify

heapify的意思上当头结点发生了变化,导致当前的结构不在是堆的结构,对此进行调整,我们画一个图,来分析一下需要的参数


图片.png
public static void heapSorted(int[] arr)
    {
        if(arr==null&&arr.length==0)
        {
            return ;
        }
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr,i);
        }
        //这个时候我们就形成了大根堆
        int size=arr.length;
        swap(arr,0,--size);
        while(size!=0)
        {
            heapify(arr,size, 0);
            swap(arr,0,--size);
        }
    }

所以我们的核心函数就变成了上述的样子,每一次都是头和尾进行交换,同时我们要注意边界,size和循环退出的条件.
接下来就是最重要的逻辑了,怎么样实现heapify

//index表示堆顶
    public static void heapify(int[] arr,int size,int index)
    {
        int left=index*2+1;
        while(left<size)//循环条件
        {
            //这是我们看一看有没有右孩子
            //left+1=right
            //为什么是小于size而不是小于等于size
            int largest=left+1<size&&arr[left+1]>arr[left]?left+1:left;
            largest=arr[largest]>arr[index]?largest:index;
            //通过上面的两个步骤我们就可以得到了index,index的左孩子,index的右孩子,其中最大的那个
            if(largest==index)//如果最大的是index,说明交换之后还是满足堆结构的,跳出循环
            {
                break;
            }
            swap(arr,index,largest);
            index=largest;
            left=index*2+1;
        }
    }

由此我们可以进行分析以下,

  • 每次比较的对象就是在index,index的左孩子,index的右孩子中产生一个最大的(我们以大顶堆为例).
  • 当比较完之后,就会产生两种情况,第一种情况index就是最大的直接break
  • 否则就交换,把较大的那个换到上面去
  • 然后继续向下走
  • 我们还需要了解到其中的循环条件为什么是left<size
    size指向的位置就是第一个不是堆结构的位置,而且堆中不存在右子树,所以 在后面我们需要left+1<size进行这个比较,这个是十分重要的

小结

int size=arr.length
swap(arr,0,--size)
while(size!=0)
{
     heapify(arr,0,size);//注意到其中的参数,index和size
     swap(arr,0,--size)
}

相关文章

  • 堆排序(一)堆排序的实现以及实现细节

    前言 堆的数据结构我们在这里不详述,堆排序总的来说一共就两步,即建立一个队使用的方式的HeapInsert和当堆顶...

  • 堆排序---基础篇

    本文主要介绍堆排序的一些基本过程和分析。 大纲 堆排序简介 堆排序代码实现 1. 堆排序简介 1.1 堆排序的存储...

  • JS实现堆排序

    原理 堆排序原理 实现 说明 堆排序对大文件很有效 堆排序是不稳定排序

  • 堆排序

    目录 1.堆排序介绍 2.堆排序图文说明 3.堆排序的时间复杂度和稳定性 4.堆排序实现 堆排序介绍 堆排序(He...

  • 堆排序的实现

    用大顶堆实现堆排序

  • 堆排序(非递归版)

    时间复杂度是O(nlogN) 但是不常用堆排序,因为堆排序不稳定 Java实现

  • 14.排序算法(5)

    1.堆排序介绍 2. 代码实现

  • 排序

    八大排序算法 一、归并排序 递归及非递归的JAVA实现 二、快速排序 快排算法JAVA实现 三、堆排序 堆排序堆排...

  • python实现堆排序(HeapSort)

    python实现【堆排序】(HeapSort) 算法原理及介绍 堆排序(Heapsort)是指利用堆这种数据结构所...

  • Javascript和堆排序

    前言 这里以递归为例,参考自慕课网刘波波老师的C++版本实现 普通堆排序(实现了一个完整的堆) 普通的堆排序首先肯...

网友评论

      本文标题:堆排序(一)堆排序的实现以及实现细节

      本文链接:https://www.haomeiwen.com/subject/bjbwiqtx.html