十大排序算法-------【堆排序】详解(Java源码)

版权声明:本文为changeyd原创文章,未经changeyd允许不得转载。谢谢合作 https://blog.csdn.net/qq_40223688/article/details/88619031

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并且同时满足堆积的性质:即子节点的键值或者索引总数小于(或者大于)它的父节点。

  1. 算法描述
    1. 将初始待排序的序列构建成为大顶堆,此堆为初始的无序区;
    2. 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,…Rn-1)和新的有序区(Rn),且满足R[1,2,…n-1]<=R[n];
    3. 由于交换后新的堆顶可能违反堆的性质,因此需要对当前无序区(R1,R2,…Rn-1)调整为新堆,然后再次将R[1]

与无序区最后一个元素交换,得到新的无序区(R1,R2…Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

  1. https://images2017.cnblogs.com/blog/849589/201710/849589-20171015231308699-356134237.gif
  2. 代码实现:完全二叉树有个特性:左边子节点位置 = 当前父节点的两倍 + 1,右边子节点位置 = 当前父节点的两倍 + 2。
  3. 代码实现:
public class DuiPaiXu2 {



       private static void daDingDui(int[] arrays, int start, int end) {



              // 父节点

              int curr = start;

              // 左右节点

              int left = curr * 2 + 1;

//           int right = curr * 2 + 2;



              // 父节点值

              int temp = arrays[curr];



              for (; left < end; curr = left, left = curr * 2 + 1) {// 将其左子节点变为父节点,将根据其变换后的父节点获取到左子节点

                    

                     if (left < end && arrays[left] < arrays[left + 1]) {// 判断左右子节点谁最大

                            left++;// 变为右子节点为父节点,

                     }



                     if (arrays[left] > temp) {// 判断左右子节点的最大值与当前父节点的值谁大

                            arrays[curr] = arrays[left];

                            arrays[left] = temp;

                     }



              }

       }



       private static void jiaoHuan(int[] arrays, int index1, int index2) {

              int temp = arrays[index1];

              arrays[index1] = arrays[index2];

              arrays[index2] = temp;

       }



       private static void duiPaiXu(int[] arrays) {

              int length = arrays.length;

              int left;



              // 从(n/2-1)--->0遍历,逐渐将待排序序列生成一个大顶堆

              for (left = length / 2 - 1; left > 0; left--) {

                     daDingDui(arrays, left, length - 1);

              }



              // 从最后一个元素开始对序列进行调整,不断的缩小调整范围,直到缩小到只含有第一个元素

              for (left = length - 1; left > 0; left--) {

//                  交换第一个和左子节点元素后,左子叶节点就是序列中最大的元素。

                     jiaoHuan(arrays, 0, left);



                     // 调整剩下的堆序列,保证右子节点为剩下的堆序列中的最大值

                     daDingDui(arrays, 0, left - 1);

              }



       }



       public static void main(String[] args) {

              int arrays[] = { 20, 30, 90, 40, 70, 110, 60, 10, 100, 50, 80 };



              System.out.println(Arrays.toString(arrays));

              duiPaiXu(arrays);

              System.out.println(Arrays.toString(arrays));



       }

}

猜你喜欢

转载自blog.csdn.net/qq_40223688/article/details/88619031
今日推荐