扣丁学堂Java培训之排序算法之堆排思想及代码实现

2019-02-13 13:26:34 403浏览

今天扣丁学堂Java培训老师给大家介绍一下关于Java排序算法之堆排思想及代码实现,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧。

什么是顶堆?它是一颗完全二叉树,顶堆有大顶堆和小顶堆两种。所谓大顶堆就是在这颗完全二叉树中,任何一颗子树都满足:父结点的值>孩子结点的值;小顶堆则相反。

如图:



什么是堆排序(Heapsort)?利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。

现在给我们一个无序数组,我们将其从小到大排序,使用堆排序的实现步骤和思想如下:

1.让这个数组变成一个大根堆

2.将最后一个位置和堆顶位置作交换

3.将堆的大小进行-1操作

4.将当前的堆变成一个大顶堆

5.回到2

看起来似乎很抽象,那我们现在用一个例子进行讲解:假设一个整型数组arr={2,1,3,6,0,5}

1.将一个无序数组变成一个大顶堆存储

如果使用完全二叉树进行存储数组,任意下标为index的结点的父结点的下标应该是(index-1)/2,其孩子结点的下标应分别为:(index*2+1)和(index*2+2)。我们使用该结论创建一个大顶堆:

首先我们假设0位置上的数已经排好,将其放在这棵二叉树的根位置,创建一个int类型变量i记录当前指向的数组的下标,初始化值为1。

设置一个index初始化值=i,将index和(index-1)/2位置的数进行比较,也就是和它的父结点进行比较,如果比父结点小就不变,并进行i++,index=i;如果比父结点大就和父结点交换并且给index赋值为(index-1)/2,即指向原来位置的父结点,再将该值与当前结点的父结点进行比较…直到该结点值是小于该结点父结点的值或到根结点时停止。

以arr数组进行举例:

0位置上的数是2,先认为它是已经排好的,i和index此时都为1,(index-1)/2为0,所以将1和2进行比较,1<2所以1位置上的数不变,执行i++,index=i;

此时i和index值都为2,(index-1)/2为0,所以讲3和2进行比较,3>2所以将3和2进行交换,原数组就变为:{3,1,2,6,0,5},index=(index-1)/2=0,当前结点是根节点,不再进行比较了,执行i++,index=i;

此时i和index值都为3,(index-1)/2为1,所以将6和1进行比较,6>1所以将6和2进行交换,原数组就变为:{3,6,2,1,0,5},index=(index-1)/2=1,不是根节点,于是再将6和3进行比较,6>3,所以再交换6和3,原数组变为:{6,3,2,1,0,5},index=(index-1)/2=0,当前结点是根节点,不再进行比较了,执行i++,index=i;

…….

以此类推最后得到的数组:{6,3,5,1,0,2}

最后得到的大顶堆:



代码实现:

// 插入数使其形成大顶堆
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;
  }
}

2.将形成的大顶堆最后一个元素和根进行交换

在该例子中应该是将2和6进行交换,得到:



得到的数组:{2,3,5,1,0,6}

那我们为什么要进行交换呢?

这时候的数组最后一个值就是最大的了,也就是最后一个位置上的数已经排好了,接下来我们就要将除了最后位置的结点之外剩下的完全二叉树进行排序了,即:



要进行排序的部分:{2,3,5,1,0}

3.将除了最后一个结点剩下的完全二叉树转化成一个新的大顶堆

传入当前数组,并标记当前位置index,初始化值为0,先判断当前的index位置的结点是否是叶子结点,如果是叶子结点就不需要再比较了,直接返回;如果不是叶子结点,则将index位置的值和它孩子结点的值进行比较,如果index位置上的值最大则不交换并且直接返回,否则选取最大的值与index位置上的值进行交换;交换后index为当前位置,再与当前位置的孩子结点进行比较。。。以此类推直到当前结点是一个叶子结点或不需要再交换时停止。

该例子中:index位置上的值是2,该位置的孩子结点分别为3和5,将2和5进行交换之后,index=index*2+2=2,此时index位置结点是一个叶子结点,不再进行交换,此时构成了一个新的大顶堆。如图:



得到的数组:{5,3,2,1,0,6}

然后就回到了步骤2,直到数组中未排序的部分只有一个数时不再进行排序。

完整代码实现:

/**
 * @author LZD   2018/03/01
 */
public class HeapSort {
  public static void heapSort(int[] arr) {
    if(arr == null || arr.length < 2)
      return;
    // 构建大顶堆
    for(int i = 0;i < arr.length;i++) {
      heapInsert(arr, i);
    }
    int heapSize = arr.length;
    swap(arr, 0, --heapSize);
    while(heapSize > 0) {
      heapify(arr, 0, heapSize);
      swap(arr, 0, --heapSize);
    }
  }
  // 插入数使其形成大顶堆
  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;
    }
  }
  // 将堆化为大顶堆
  public static void heapify(int[] arr, int index, int heapSize) {
    // 先判断当前的index位置的结点是否是叶子结点
    int left = index * 2 + 1;
    while(left < heapSize) {
      // 不是叶子结点则选出index位置结点的孩子结点中较大的赋给largest
      int largest = left+1 < heapSize && arr[left + 1] > arr[left]
          ? left + 1: left;
      largest = arr[largest] > arr[index] ? largest : index;
      if(largest == index) {
        break;
      }
      swap(arr, largest, index);
      index = largest;
      left = index * 2 + 1;
    }
  }
  public static void swap(int[] arr, int i, int j) {
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
  }
  // for test 打印数组
  public static void printArray(int[] arr) {
    for(int i = 0;i < arr.length;i++) {
      System.out.print(arr[i] + " ");
    }
    System.out.println();
  }
  // for test
  public static void main(String[] args) {
    int[] arr = {2, 1, 3, 6, 0, 5};
    heapSort(arr);
    printArray(arr);
  }
}

以上就是关于扣丁学堂Java培训之排序算法之堆排思想及代码实现的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,最后想要了解更多请关注扣丁学堂Java培训官网、微信等平台,扣丁学堂IT职业在线学习教育平台不仅为您提供权威的Java视频教程供大家学习,还精心的准备了Java从入门到精通开发实战技能,定能让你学有所成。扣丁学堂Java技术交流群:670348138

扣丁学堂微信公众号


【关注微信公众号获取更多学习资料】


查看更多关于“Java开发资讯”的相关文章>>

标签: Java培训 Java视频教程 Java多线程 Java面试题 Java学习视频 Java开发

热门专区

暂无热门资讯

课程推荐

微信
微博
15311698296

全国免费咨询热线

邮箱:codingke@1000phone.com

官方群:148715490

北京千锋互联科技有限公司版权所有   北京市海淀区宝盛北里西区28号中关村智诚科创大厦4层
京ICP备12003911号-6   Copyright © 2013 - 2019

京公网安备 11010802030908号