树型排序
原本的待排序列为第1层,然后两两分组,接着从分组中间找出每一个分组中的较小的值,得到第2层,接着从第二层再分组,再找最小值,依次类推,直到整个待排序列中的最小值得出只有应该的时候,停止比较。
现在开始应该考虑输出过程了:
将所有的含有13的结点全部变为无穷大符号,
接着继续比较,27小于无穷大,所以27选出,27又小于38,所以27变为根节点,也就是整棵树当前的最小值。
如此排序下去,也可以完成排序操作。
堆排序
堆的数组表示方法
堆是一棵完全二叉树,其中每个结点的关键字都大于其孩子结点的关键字。
大顶堆:所有子树中的根结点的值都大于下面的所有子节点。用于升序排序。
小顶堆:所有子树中的根节点的值都小于下面的所有子节点。用于降序排序。
所以,每个结点的左孩子都是当前结点的下标的二倍,右孩子是当前结点下标的2被+1。
因此,引出了其数组表达方式:
数组中存储二叉树结点的次序是根、左、右。
Java实现代码
package com.xingyun.paixu;
import java.util.Arrays;
public class HeapSort {
/*
* 堆排序
*
* */
public static void main(String[] args) {
int[] arr = new int[] {9,6,8,7,0,1,10,4,2};
/*
//每一次都是从最后一个非叶子 结点开始比较的。
int start=(arr.length-1)/2;
//每一次都是与第一个元素,也就是根节点进行交换的,所以不需要比较循环到0;
for(int i=start;i>=0;i--) {
MaxHeap(arr, arr.length, i);
}
*/ HeapSort(arr);
System.out.println(Arrays.toString(arr));
}
//2、开始排序
public static void HeapSort(int[] arr) {
//每一次都是从最后一个非叶子 结点开始比较的。
int start=(arr.length-1)/2;
//调整为大顶堆
for(int i=start;i>=0;i--) {
MaxHeap(arr, arr.length, i);
}
//交换位置。将从最后一个开始与第一个元素交换,因为每一次都是与第一个元素进行交换,所以不需要遍历到0
//将数组中的第0个和堆中的最后一个进行交换,然后再把前面的进行大顶堆构建
for(int i=arr.length-1;i>0;i--) {
int temp=arr[i];
arr[i]=arr[0];
arr[0]=temp;
MaxHeap(arr, i, 0);
}
}
//1、将数组转为大顶堆
public static void MaxHeap(int[] arr,int size,int index) {
//左子节点
int leftNode=2*index+1;
//右子结点
int rightNode=2*index+2;
//先暂定当前结点为最大值
int max=index;
//注意这里需要判断左右子结点是否存在,不加判断的话会发生数组下标越界的错误
//然后比较当前结点和左右两个子节点的值的大小,从这三个结点当中取出应该最大的结点值最为这三个结点的跟结点
if(leftNode<size&&arr[max]<arr[leftNode]) {
max=leftNode;
}
if(rightNode<size&&arr[max]<arr[rightNode]) {
max=rightNode;
}
//如果发生交换行为,需要判断交换位置后的子结点是否满足大顶堆条件,是否大于它的所有子节点
if(max!=index) {
int temp=arr[index];
arr[index]=arr[max];
arr[max]=temp;
MaxHeap(arr, size, max);
}
}
}