在众多排序方法当中,主流的排序总共有七种,接下来的博客,我试着给大家分享一下自己的心得.
堆排序
上一篇博客当中,在讲解对象的比较方法时顺带着说了一下堆的特性,那么今天我们趁热打铁,拿下堆排序!!
我们就直接在代码中进行讲解
public class Heap {
int usedSize;//本来堆的底层是要有一个数组的,但是堆排序是要直接在原数组
//上面动刀,所以我直接数组传参了
//交换函数
public void swap(int[]ele,int i,int j){
int tmp=ele[i];
ele[i]=ele[j];
ele[j]=tmp;
}
//对于堆排序来说,如果我们想要一个升序的数组,那么我们首先就要创建一个小
//根堆,不能创建一个大根堆的原因很简单,我们只能保证堆顶的左右比根顶小
//那左右两个元素之间的大小关系我们是没法保证的
public void createHeap(int[] ele){
usedSize= ele.length;
int parent=(usedSize-1-1)/2;
for(int i=parent;i>=0;i--){
shiftDown(ele,i,usedSize);//向下调整
//向下调整顾名思义:就是从堆顶开始往下面逐步调节,一开始我不能够理解
//的原因就是没有发现这是一个循环,所以我们是对除了最后一排都进行了
//向下调整
}
}
public void shiftDown(int[]ele,int parent,int len){
int child=2*parent+1;
while(child<len){//向下调整也不能越界,而我们的边界就是子节点不可以
//超过数组
if(child+1<len&&ele[child]<ele[child+1]){
child++;//挑选子节点中较大的那个进行操作
}
if(ele[child]>ele[parent]){
swap(ele,child,parent);
}
parent=child;
child=2*parent+1;
}
}
//对于堆排序重点就在于堆的特性,就是堆顶的那个要不就是最大,要不就是
//最小因此我们把堆顶元素和数组尾巴元素进行交换,那么最后的位置也就
//确定了下来,此时因为末尾元素已经确定,我们可以把数组当少了一个看
//但是此时我们交换上去的堆顶元素在堆顶中是唯一一个不稳定的元素
//我们需要对堆顶元素进行向下调整,这样子慢慢地慢慢地,数组中每个位置
//的元素就都归位了
public void heapSort(int[] ele){
int num=usedSize;
while(num>0) {
swap(ele,0,num-1);
shiftDown(ele,0,--num);
}
}
//向上调整
public void shiftUp(int[]ele,int child){
int parent=(child-1)/2;
while(parent>=0){
if(ele[parent]<ele[child]){
swap(ele,parent,child);
}else{
break;
}
child=parent;
parent=(child-1)/2;
}
}
//增加元素
public void add(int []ele,int key){
if(usedSize==ele.length){
ele= Arrays.copyOf(ele,ele.length+3);
}
ele[usedSize++]=key;
shiftUp(ele,usedSize-1);
}
}
最后我们用图来演示一下:
一个无序数组:
建立了一个大根堆:
第一次首尾交换:
安置好最后一位后,调整大根堆:
重复上述操作:
…最后:
一个崭新的升序数组就好啦!!!
希望我这篇绘声绘色地博客能够帮助到大家!!
百年大道,你我共勉!!!