大根堆排序

大根堆排序(HeapSort)

每个根结点都比子树的任意结点大

将数组当成一个完全二叉树 比如说:[2,5,8,7,6,9,1]

2

5 8

7 6 9 1

我们需要调用两个方法:heapInsert插入和hepify重排

heapInsert插入:从最后一个元素开始从下往上 找自己的头结点,如果比头结点大,则与其交换(头结点的位置 = 现结点位置-1 >>1)

举个例子:1比自己的头结点8小,所以不动   9比头结点大,所以交换

hepify重排(当我们改变index下的元素,想要重新排序堆时使用此方法):

定义一个heapsize = arr.length

从index结点从上往下找比自己大的(左节点的位置 = 现结点位置*2+1,右节点位置 = 现结点位置*2+2)

Void hepify(arr,index,heapsize){

Int left = index*2 +1;

//只要左节点没有超过heapsize那么一直比较(通俗的说就是让它往下沉)

While(left < heapsize){

Int largest = 比较左结点和右结点哪个大

Largest = 比较左结点和右节点较大值与index结点

如果largest就是index本身的话则跳出循环

否则

交换index元素与largest元素

Index = largest

Left = index<<2+1;

}

}


package xyz.yeidi.sort;

public class HeapSort {

public static void main(String[] args) {

int [] arr = new int [] {1,7,5,8,4,3,6};

//使用heapInsert方法将数组arr排序

// for(int i=0;i<arr.length;i++) {

// //此方法初始化堆的时间复杂度为O(N*logN)

// heapInsert(arr,i);

// }

//使用heapify方法初始化堆可以优化时间复杂度(O(N))  叶子结点都不用下沉了

//所以只需要从非叶子结点开始即可

for(int i=(arr.length-1-1)>>1;i>=0;i--) {

heapify(arr,i,arr.length-1);

}

for(int a : arr) {

System.out.println(a);

}

System.out.println();

//假设1坐标下的7变小  7 - >2  使用heapify重排序

arr[1] = 2;

int heapsize = arr.length - 1;

heapify(arr,1,heapsize);

for(int a : arr) {

System.out.println(a);

}

}

public static void heapInsert(int []arr,int index) {

while(index-1>>1 >=0 && arr[index] > arr[index-1>>1]) {

swap(arr,index,index-1>>1);

index = index-1>>1;

}

}

//如果index坐标下的元素变小了,使用heapify方法将这个元素下沉

public static void heapify(int []arr,int index,int heapsize) {

int left = index*2 +1;

while(left < heapsize) {

//先进行左右元素的比较,得到较大元素的下标

int largest = arr[left] > arr[left+1] && left + 1<heapsize ? left:left+1;

largest = arr[index] > arr[largest] ? index : largest;

//如果最大值就是index下标元素本身的话,则跳出循环

if(index == largest) break;

swap(arr,index,largest);

index = largest;

left = index*2+1;

}

}

//交换元素的方法

public static void swap(int []arr,int a,int b) {

arr[a] = arr[a] ^ arr[b];

arr[b] = arr[a] ^ arr[b];

arr[a] = arr[a] ^ arr[b];

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值