完全二叉树
完全二叉树与数组的对应关系:
在数组中,下标为i的节点,其左孩子在2*i+1,右孩子在2*i+2,其父节点在(i-1)/2。
也可以说,并不存在实际的完全二叉树,完全二叉树的实际结构可以理解为数组结构。由一个数组可以构造一个完全二叉树。
堆
堆就是完全二叉树,分为大顶堆和小顶堆。大顶小顶的含义是,整个树中的最大值或最小值为树的根节点,任意子树的根结点也是该子树的最大值或最小值。
当某个节点x的值变小时,如何更新堆?
当其子节点不为空时,若x小于其子节点(小于一个或两个),将x与x的左右子节点的最大值交换,若交换后,x的子节点仍然不为空,且x小于其子节点,继续交换。
堆排序算法图解:懒得画图,参考堆排序算法图解
本人的Demo
package heapSort;
import java.util.Arrays;
import java.util.Random;
class HeapUtil {
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); //将最大值放在最后,堆长度减1
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) {
int left = 2 * index + 1;
while (left < heapSize) {
int largest = left + 1 < heapSize && arr[left+1] > arr[left]
? left + 1 : left; //largest:最大子节点的下标
largest = arr[largest] > arr[index] ?largest : index;
if (largest == index) //该结点>子节点,停止比较。
break;
swap(arr, largest, index); //将该节点与较大子节点交换
index = largest; //继续向下比较
left = index * 2 + 1;
}
}
private static void swap(int[] nums, int i, int i1) {
int tmp = nums[i];
nums[i] = nums[i1];
nums[i1] = tmp;
}
}
/**
* @ClassName HeapSortDemo
* @Description TODO
* @Author
* @Date 19-7-18 上午9:27
**/
public class HeapSortDemo {
public static int[] produceRandomArray(int bound) {
Random random = new Random();
int[] data = new int[20];
for (int i = 0; i < data.length; i++) {
data[i] = random.nextInt(bound);
}
return data;
}
public static void main(String[] args) {
int[] data = produceRandomArray(100);
System.out.println(Arrays.toString(data));
System.out.println("************ heap sort: ***********");
HeapUtil.heapSort(data);
System.out.println(Arrays.toString(data));
}
}