一.堆排序的概念
- 堆排序:就是利用堆这种数据结构来进行排序的一种算法思想,它是选择排序的一种,它包括大根堆和小根堆,都是完全二叉树。
- 完全二叉树:除最后一层外,其他每一层都被完全填充,并且所有的结点保持向左对齐。
- 满二叉树:除叶子结点外,每个结点都有两个孩子,每一层都被完全填充。
- 完满二叉树:除叶子结点外每个结点都有两个孩子。
- 大根堆:每个结点的值都大于等于它左右子结点的值
- 小根堆:每个结点的值都小于等于它左右子结点的值
如图所示这两种堆的结构映射到数组后,就是 9,5,8,2,3,4,7,1和1,3,5,4,2,8,9,7
所以在数组arr中大根堆和小根堆的公式如下:
-
大根堆:arr[i] >= arr[2i + 1] && arr[i] >= arr[2i + 2]
-
小根堆:arr[i] <= arr[2i + 1] && arr[i] <= arr[2i + 2]
二.堆排序的基本思想
1.建堆
建堆就是建立大根堆或者小根堆,这里就以大根堆为例讲一下,
2.取值
成功建堆之后,下面就是取值了,大根堆的根就是这组数中的最大值。
思想:将根结点与大根堆的最后一个元素交换位置,然后除最后一个元素外剩下的元素再进行调整,调整为大根堆,然后根结点的元素就是次最大元素,继续前面的步骤。
三.代码
package com.westmo1.demo2;
import java.util.Arrays;
import java.util.Scanner;
public class MyDemo3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("输入数据");
int[] ints = new int[7];
for (int i = 0; i < ints.length; i++) {
int i1 = scanner.nextInt();
ints[i]=i1;
}
int length=ints.length-1;
int root=ints.length/2-1;
for (int i = root; i >=0; i--) {
BuildHeap(ints, length, i);
}
//取值,把根结点元素和最后一个元素交换
for (int i = 0; i <ints.length; i++) {
swap(ints,0,length);
length--;
BuildHeap(ints,length,0);
}
System.out.println(Arrays.toString(ints));
}
//建立大根堆
public static void BuildHeap(int arr[],int length,int root){
int leftcode=root*2+1;
int rightcode=root*2+2;
int max=root;
if(leftcode<length&&arr[leftcode]>=arr[max]){
max=leftcode;
}
if(rightcode<length&&arr[rightcode]>=arr[max]){
max=rightcode;
}
if (max!=root) {
swap(arr,max,root);
//调整完之后,可能会影响到下面的子树,需再次调整
BuildHeap(arr,length,max);
}
}
private static void swap(int[] arr, int i, int j) {
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
来源:CSDN
作者:锦鱼不忘旧时晨
链接:https://blog.csdn.net/weixin_44324174/article/details/104183349