【算法基础(4)】堆排序(二)

堆排序(二)

把数组从零开始连续的一段 = 完全二叉树 size

i 左 son 2*1+1

i 右 son 2*1+2

父 (i-1) / 2

堆是完全二叉树,分为大根堆和小根堆

在完全二叉树里,每一棵子数最大的值是头节点的值,就是大根堆

同理,在完全二叉树里,每一棵子数最小的值是头节点的值,就是小根堆

大根堆排序,插入的值 和 父节点比较,如果比父节点大,和它交换,直到最大,就停止,通过这样的调整,得到的一定是大根堆。这个过程,我们叫做 heapInsert

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; 
  }
}

从一堆数中找出最大值,移除它,保持还是大根堆,我们管这个过程叫做heapify

public static void heapify(int [] arr, int index, int heapSize) {
  int left = index * 2 + 1; // 左孩子的下标
  while (left < heapSize) { // 下方还有孩子 (左孩子越界,那么就没有右孩子了。)
    // 俩个孩子中,谁的值大,把下标给谁 (先找出孩子中最大的)
    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; // 找左孩子继续 while
  }
}

题目:

已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过K,并且K相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。

假如K = 6 ,建立一个heapSize = 7 的小根堆 (这样小根堆的最小值一定是数组的最小值)

把最小的弹出,保持小根堆,新加入的数字做heapfiy,

继续上面的步骤,直到全部弹出。

public static void main(String[] args) {
  PriorityQueue<Integer> heap = new PriorityQueue<>();
  
  heap.add(8);
  heap.add(4);
  heap.add(10);
  heap.add(3);
  
  while(!heap.isEmpty) {
    System.out.println(heap.poll());
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

左钦杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值