-
堆排序代码如下(注释见下):
-
首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的堆顶
-
将堆顶的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为
n-1
-
将剩余的
n-1
个数再构造成大根堆,再将堆顶数与n-1
位置的数交换,如此反复执行,便能得到有序数组
public class Main { void heapSort(int[] a, int n){ for(int i = n / 2 - 1; i >= 0; i--){ adjustHeap(a, i, n); } for(int i = n - 1; i > 0; i--){ int temp = a[0]; a[0] = a[i]; a[i] = temp; adjustHeap(a, 0, i); } } void adjustHeap(int[] a, int i, int n){ int largest = i; int l = 2* i + 1; int r = 2* i + 2; if(l < n && a[largest] < a[l]){ largest = l; } if(r < n && a[largest] < a[r]){ largest = r; } if(largest != i){ int temp = a[largest]; a[largest] = a[i]; a[i] = temp; adjustHeap(a, largest, n); } } }
-
-
测试用例:
public class Main { public static void main(String[] args) { int[] a = {8,4,5,7,1,3,6,2}; int n = 8; heapSort(a, n); for(int i = 0; i < a.length; i++){ System.out.print(a[i] + " "); } //System.out.println(Arrays.toString(a)); //Arrays.toString()方法是方便数组类型输出,不用使用for遍历数组 } static void heapSort(int[] a, int n){ //1.建堆 for(int i = n / 2 - 1; i >= 0; i--){//从第一个非叶节点开始,从下往上进行判断,每个节点都要维护堆的性质 adjustHeap(a, i, n); } //2.排序 for(int i = n - 1; i > 0; i--){//i必须>0,不能等于 //交换堆顶元素和末尾元素 int temp = a[0]; a[0] = a[i]; a[i] = temp; //维护剩余元素的堆的性质 adjustHeap(a, 0, i);//0表示从堆顶元素开始维护,i表示剩余的元素个数,原来是n个,现在是n-1个,即i个 } } //维护堆的性质(保证是一个大顶堆) static void adjustHeap(int[] a, int i, int n){//i为待维护的节点下标,n为数组长度 int largest = i;//i节点为当前父节点 int l = 2* i + 1;//左子节点 int r = 2* i + 2;//右子节点 //找出父节点,左子节点,右子节点中最大值的那个下标largest if(l < n && a[largest] < a[l]){//如果左子节点存在,且大于父节点 largest = l;//交换下标 } if(r < n && a[largest] < a[r]){//如果右子节点存在,且大于父节点 largest = r;//交换下标 } if(largest != i){//如果i位置的节点有孩子比他大 //交换节点的值,让最大节点的值跑到父节点上,i节点的值跑到了左右孩子上 int temp = a[largest]; a[largest] = a[i]; a[i] = temp; //递归处理每个子树,当前需要维护的节点下标为largest adjustHeap(a, largest, n); } } }
输出结果
(1)Arrays.toString(a)
输出结果:
(2)for
循环输出结果:
面试手撕堆排序
最新推荐文章于 2025-04-07 13:47:03 发布