大顶堆排序 =^=
把数组处理为大顶堆(或小顶堆)格式,即父节点大于(或小于)两个叶子节点,如不符合要求就把叶子节点的值和父节点的值互换,但是要注意,如果这个叶子节点还有爷爷节点,也需要比较一下
左叶子 2*i + 1
右叶子 2*i + 2
如 num [8,9,11,13],i=0时 num[i]父节点8比 左叶子num[2*0+1] 9小 -> num[9,8,11,13]
之后比较父节点与右叶子,9比num[2*0+2]11小,num[11,8,9,13]
游标往后一位,8的左叶子是13,需要更换为num[11,13,9,8]
这时候就发现会有13比11还大的情况
所以我干脆直接重新排起,然后把一整个数组处理完,第一个值肯定是最大的,当然这是大顶堆做法,小顶堆做法父节点叶子节点比较的时候反一反就可以了。
大顶堆排序代码在下面,如有问题欢迎指出 :
import java.util.*; //最好不要直接用*
public class Main{
public static void main(String [] args) throws Exception {
Scanner sc = new Scanner(System.in);
// 9 6 8 10 3 4 7 2 1 测试用例输入
String[] s = sc.nextLine().split(" ");
int num[] = new int[s.length];
for(int i = 0 ; i < s.length; i++){
int integer = Integer.parseInt(s[i]);
num[i] = integer;
}
int res[] =new int[s.length]; //创建一个res数组存放结果
int[] heapsort = heapsort(num, res); //调用排序方法
for(int i = 0 ; i < heapsort.length; i++){
System.out.print( heapsort[i] + " ");
}
}
private static int[] heapsort(int[] num,int[]res) {
buildheap(num,res);
return res;
}
private static int[] buildheap(int[]num,int[] res) {
sort(num);
if(num.length==1){ // 出口
res[0] = num[0]; // 还剩一个值没换,执行不到下面的语句了,直接换了返回完事
return res;
};
// num 原始数组按照大顶堆逻辑处理后,数组第一个节点即为最大的父节点,保存到res[num.length-1] 的位置
int temp = num[num.length-1];
num[num.length-1] = num[0];
num[0] = temp;
int newnum[] = new int[num.length-1];
for(int i = 0; i< newnum.length;i++){
newnum[i] = num[i];
}
res[num.length-1] = num[num.length-1]; // 最大的值单独放到res里
return buildheap(newnum,res);
}
public static int[] sort(int num[]){
int k = 0;
for(int i = 0 ; i < num.length/2; i++){
if(2*i+2>=num.length){ //限制溢出,比较笨,不知道是不是只能这么写
break;
}
// 顺序排 使用大顶堆 左孩子 2*i+1 右孩子 2*i+2 左右孩子比父节点小, 如果大于跟就置换
if(num[i] < num[2*i+1]){
int temp = num[2*i+1];
num[2*i+1] = num[i];
num[i] = temp;
k++; //如果替换了,就需要重新排序,因为叶子节点比父节点大 也可能比爷爷节点大
}
if(num[i] < num[2*i+2]){
int temp = num[2*i+2];
num[2*i+2] = num[i];
num[i] = temp;
k++;
}
if(k!=0){
sort(num);
}
}
return num;
}
}
以后每一种算法都要尝试自己写下来,那才是自己的东西,完结,撒花~