一、堆排序
1.实现步骤:
1)构造堆
2)得到对顶元素,这个值就为最大值
3)交换对顶元素和数组中最后一个元素,此时堆中最大的元素已经放到最后合适的位置
4)对堆进行下沉调整,重新让出过最后一个元素剩余 的元素的最大值放到堆顶
注意:在下沉操作时,只需从堆的长度的一半处进行调整就行;
因为:假设堆长度为k,一半处的节点的索引为k/2,那么它的左子节点的索引为k,由此看出一半处的节点为该堆的倒数第二层,则不需要再到最后一层了。
5)重复3、4步骤,直到剩下一个元素位置
public class HeapSort { //判断heap堆中索引i处的元素是否小于索引j处的元素 public static boolean less(Comparable[] heap,int i,int j ){ return heap[i].compareTo(heap[j])<0; } //交换heap堆中i和j处的元素 public static void exch(Comparable[] heap,int i,int j){ Comparable temp = heap[i]; heap[i]=heap[j]; heap[j]=temp; } //根据原数组source,构建堆heap private static void creatHeap(Comparable[] source,Comparable[] heap){ //把source数组中的元素赋值到heap中,heap就形成一个无序的堆 System.arraycopy(source,0,heap,1,source.length); //对堆进行下沉操作(从堆的长度的一半处进行调整) for (int i=(heap.length/2);i>0;i--){ sink(heap,i,heap.length-1); } } //堆source数据进行从小到大的排序 public static void sort(Comparable[] source){ //构建堆 Comparable[] heap=new Comparable[source.length+1]; creatHeap(source,heap); //定义一个变量,记录未排序的元素中最大的索引 int N=heap.length-1; //通过循环,交换1索引处的元素和未排序时的最大索引处的元素 while (N!=1){ //交换元素 exch(heap,1,N); //让排序后最大元素所在的索引不要参与下沉调整 N--; //对1处的元素进行下沉调整 sink(heap,1,N); } //把heap中的数据复制到source中 System.arraycopy(heap,1,source,0,source.length); } //再heap堆中,对target位置的元素做下沉操作,范围为0-range private static void sink(Comparable[] heap,int target,int range){ while (2*target<=range){ //找出当前子节点的较大值 int max=0; if(2*target+1<=range){ if (less(heap,2*target,2*target+1)){ max=2*target+1; }else { max=2*target; } }else{ max=2*target; } //比较当前节点和较大字节的值,小于则交换, if (!less(heap,target,max)){ break; } exch(heap,target,max); target=max; } } }