小(大)顶堆的各种操作与应用场景(基于Java)

package algroithm;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @Author Snail
 * @Describe 用于堆算法的测试
 * @CreateTime 2019/7/25
 * 

*

* 堆中父子节点索引的关系: * childIndex=parentIndex*2+1(左节点在数组中的索引) * childIndex=parentIndex*2+2(右节点在数组中的索引) */ public class TestHeap { public static void main(String[] args) { //1. 将任意一个数组构建为小顶堆 int[] arr = new int[]{7, 1, 3, 10, 5, 2, 8, 9, 6}; buildHeap(arr); System.out.println(Arrays.toString(arr)); //[1, 5, 2, 6, 7, 3, 8, 9, 10] //2. 交换堆顶元素与末尾元素 + 调整堆结构:得到堆排序后的有序数组 for (int i = arr.length - 1; i > 0; i--) { swap(arr, 0, i); downAdjust(arr, 0, i); } System.out.println(Arrays.toString(arr));//[10, 9, 8, 7, 6, 5, 3, 2, 1] /** *1中堆构建的时间复杂度为O(n),2中堆调整的时间复杂度为nlog(n),所以认为堆排序的时间复杂度为O(nlog(n)) */ //加入一个元素到小顶堆中(加入元素到堆中,自能将新元素加在数组最后) Scanner scanner = new Scanner(System.in); int childNode = Integer.parseInt(scanner.nextLine());//0 int[] arrHeap = new int[]{1, 5, 2, 6, 7, 3, 8, 9, 10}; arrHeap = upAdjust(arrHeap, childNode); System.out.println(Arrays.toString(arrHeap));//[0, 1, 2, 6, 5, 3, 8, 9, 10, 7] //删除堆顶元素,堆中每次都只能删除第0个数据,并将最后一个元素放到数组的0位置 arrHeap = delNode(arrHeap); System.out.println(Arrays.toString(arrHeap));//[1, 5, 2, 6, 7, 3, 8, 9, 10] } private static void swap(int[] arr, int i, int i1) { int temp = arr[i]; arr[i] = arr[i1]; arr[i1] = temp; } /** * 构建一个小顶堆(任何一个父节点的值,都小于等于它左右孩子节点的值) * * @param arr 待调整的堆 */ public static void buildHeap(int[] arr) { // 从最后一个非叶子节点开始到根节点,依次下沉调整 for (int i = arr.length / 2; i >= 0; i--) { downAdjust(arr, i, arr.length); } } /** * 堆中某个元素的下沉调整 * * @param arrHeap 待调整的堆 * @param parentIndex 下沉的节点 * @param length 堆数组的长度 */ public static void downAdjust(int[] arrHeap, int parentIndex, int length) { //保存父节点值,避免元素交换,并用于最后的赋值 int temp = arrHeap[parentIndex]; int childIndex = parentIndex * 2 + 1; while (childIndex < length) {//表示节点还没下沉到数组的最后位置 //判断是否存在右节点,并找到两个孩子节点的最小值 if (childIndex + 1 < length && arrHeap[childIndex] > arrHeap[childIndex + 1]) { childIndex++; } //如果父节点小于孩子节点的最小值,则证明他不需要下沉了 if (temp <= arrHeap[childIndex]) { break; } //将孩子节点上浮到父节点位置 arrHeap[parentIndex] = arrHeap[childIndex]; parentIndex = childIndex; childIndex = parentIndex * 2 + 1; } arrHeap[parentIndex] = temp; } /** * 堆中元素的上浮调整,上浮最后一个元素 * * @param arrHeap 待调整的堆 * @param childNode */ public static int[] upAdjust(int[] arrHeap, int childNode) { //复制数组到新的空间 int childIndex = arrHeap.length; int[] newHeap = new int[childIndex + 1]; System.arraycopy(arrHeap, 0, newHeap, 0, childIndex); //上浮元素 newHeap[childIndex] = childNode; int parentIndex = (childIndex - 1) / 2; while (childIndex > 0 && childNode < newHeap[parentIndex]) { //将parent节点替换到child节点 newHeap[childIndex] = newHeap[parentIndex]; childIndex = parentIndex; //获取父节点的父节点 parentIndex = (parentIndex - 1) / 2; } newHeap[childIndex] = childNode; return newHeap; } /** * 删除小顶堆中堆顶 * * @param arrHeap * @return */ private static int[] delNode(int[] arrHeap) { //构建新数组地址空间 int[] newHeap = new int[arrHeap.length - 1]; System.arraycopy(arrHeap, 0, newHeap, 0, arrHeap.length - 1); newHeap[0] = arrHeap[arrHeap.length - 1]; downAdjust(newHeap, 0, newHeap.length); return newHeap; } }

堆排序算法的时间复杂度可认为是O(nlog(n))

算法实现可参考:https://mp.weixin.qq.com/s/cq2EhVtOTzTVpNpLDXfeJg

你可能感兴趣的:(算法与数据结构)