0
点赞
收藏
分享

微信扫一扫

最容易理解的堆排序——Java实现


排序过程
这里以构建大顶堆为例:

  1. 先构建一个大顶堆,构建过程:利用批量建堆——从下而上的下滤方法构造出一个符合性质的大顶堆,
  2. 其中批量建堆的方法是从叶子节点开始下滤,即
    elements[(array.length >>1) - 1]处开始直到根节点。
  3. 建造成功之后,此时elements[0]为最大的元素
  4. 一个swap函数,返回值为数组,将elements数组传入。将该elements数组的第0位元素和最后一位元素替换,并把返回结果赋值给elements,一定要记住更新elements数组。其实也就相当于删除最大元素之后根节点下滤。
  5. 将此时的elements的最后一位元素加入结果数组中。
  6. 重复4,5步骤。
  7. 返回result数组。
    源代码

方法:

public static int[] heapSort(int[] array){
int[] result = new int[array.length];
int j = 0;
int len = array.length;
for (int i = len-1; i >= 0; i--){
int temp[] = Arrays.copyOfRange(array,0,len2--);
heapify(temp);
array = swap(temp,0,i);
result[j++] = temp[i];
}
return result;
}
public static int[] swap(int[] array, int index1, int index2){
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
return array;
}

/**
* 下滤
* @param index
* @param array
*/
public static void siftDown(int index, int[] array) {
int element = array[index];
int half = array.length >> 1;
// 第一个叶子节点的索引 == 非叶子节点的数量
// index < 第一个叶子节点的索引
// 必须保证index位置是非叶子节点
while (index < half) {
// index的节点有2种情况
// 1.只有左子节点
// 2.同时有左右子节点

// 默认为左子节点跟它进行比较
int childIndex = (index << 1) + 1;
int child = array[childIndex];

// 右子节点
int rightIndex = childIndex + 1;

// 选出左右子节点最大的那个
if (rightIndex < array.length && array[rightIndex] > child) {
child = array[childIndex = rightIndex];
}

if (element >= child) break;

// 将子节点存放到index位置
array[index] = child;
// 重新设置index
index = childIndex;
}
array[index] = element;
}

/**
* 批量建堆
* @param array
* @param
*/
//自下而上的下滤
public static void heapify(int[] array){

for (int i = (array.length >>1) - 1; i >= 0; i--){
siftDown(i,array);
}
}

主函数:

public static void main(String[] args){

int[] arr = {1,3,5,2,4,7,8};
System.out.println(Arrays.toString(heapSort(arr)));

}

运行结果:

最容易理解的堆排序——Java实现_java


大家应该会发现这个算法会有点浪费性能(多次调用数组分割函数,新建数组进行从下而上的下滤操作),这也是我在csdn上第一次看到的堆排序思路。确实非常浪费性能,​​点此进入堆排序升级版​​


举报

相关推荐

0 条评论