算法之堆排序

是一种数据结构,是具有特定条件(任何节点大于等于子节点的值(左右子节点大小没有定义))的顺序存储(树从树根开始 从上到下从左到右依次存储到数组里)的完全二叉树
思想:
1.将待排序序列构建成大小顶堆(大顶堆升序 反之降序)
从最后一个非终端节点(n/2 n是数据总数 得到结果向下取整 获得最后一个非终端节点的下标)层进行调整,然后在一层层往上(从下往上),一直到根
2.此时最大(小)的值位于根节点
3.将其和末尾元素进行交换 此时末尾元素就是最大(小)元素
4.将n-1个元素重新构造堆,反复进行 2 3

堆排序是不稳定的,时间复杂度为nlogn

大顶堆和小顶堆
在这里插入图片描述

来个图
在这里插入图片描述

代码实现:

	package heapSort;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {4, 6, 8, 5, 9, -1, 90, 89, 56, -999};
        isHeapSort(arr);
        System.out.println(Arrays.toString(arr));
    }


    //堆排序方法
    public static void isHeapSort(int[] arr) {
        int temp = 0;
        //i是顺序存储的最后树根的下标  从右至左  从下至上   i>=0 0是数的树根
        for (int i = arr.length / 2 - 1; i >= 0; i--) adjustHeap(arr, i, arr.length);
        //调整完了  只是一颗局部树,但是树根和末尾元素没有交换
        //交换  i是数组长度  每交换一次 长度-1
        for (int i = arr.length - 1; i > 0; i--) {
            temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            //调整一次交换一次  之后继续调用
            adjustHeap(arr, 0, i);
        }
    }

    //最后的树根索引 从下至上调整
    //将数组调整成大顶堆
    //arr 待调整的数组
    //i 表示要调整的节点(有子节点)索引
    //len  表示对多少个元素进行调整,len是在主逐渐减少
    public static void adjustHeap(int[] arr, int i, int len) {
        //把要调整的局部树根的值保存下来
        int temp = arr[i];
        //j=左子节点  循环一次后 左子节点的左子节点 类似递归
        for (int j = i * 2 + 1; j < len; j = j * 2 + 1) {
            //左<右  并且k+1不能大于总长度
            if (j + 1 < len && arr[j] < arr[j + 1]) {
                //指向右子节点 j是索引  j++的索引比j大1,因为是顺序存储二叉树  if执行完毕  左右孩子最大节点出现
                j++;
            }
            //左右节点中大的值和当前的树根(父节点)比较
            //大于树根
            if (arr[j] > temp) {
                arr[i] = arr[j];
                i = j;
            } else {
                //小于树根
                break;
            }

        }
        //for 循环结束 当前i为树根的树调整完毕
        //把temp放到调整后的位置
        arr[i] = temp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值