堆排序-java版

1、堆的定义

n个元素的序列{k1,k2,…,kn}称之为堆,当且仅当满足以下条件时:

 

2、大顶堆和小顶堆

 

package com.niki.algorithm.util;

import java.util.Arrays;

/**
 * Created by IntelliJ IDEA.
 * User: niki.yang
 * Date: 2020/11/9
 */
public class HeapSort {
    public static void main(String[] args) {
        int[] arr = { 4,1,9, 8,15,10, 3,2,-1};
        //在堆排序之前,打印初始数组
        System.out.println(Arrays.toString(arr));
        //进行堆排序
        heapSortEsc(arr);
        //进行堆排序之后
        System.out.println("升序:" + Arrays.toString(arr));
        heapSortAsc(arr);
        System.out.println("降序:" + Arrays.toString(arr));
    }

    /**
     * @Description :升序
     * @Author : yarm.yang
     * @Date : 2020/11/9 17:09
    */
    public static void heapSortEsc(int[] arr){
        // 建立大根堆
        buildMaxHeap(arr);
        for (int i = arr.length - 1; i >= 1; i--) {
            swap(arr,0, i);
            maxHeapAdjust(arr, i, 0);
        }
    }

    /**
     * @Description :降序
     * @Author : yarm.yang
     * @Date : 2020/11/9 17:08
    */
    public static void heapSortAsc(int[] arr){
        // 建立小根堆
        buildMinHeap(arr);
        for (int i = arr.length - 1; i >= 1; i--) {
            swap(arr,0, i);
            minHeapAdjust(arr, i, 0);
        }
    }


    private static void buildMaxHeap(int[] arr) {
        int half = arr.length/2;
        for (int i = half; i >= 0; i--) {
            maxHeapAdjust(arr, arr.length, i);
        }
    }

    private static void buildMinHeap(int[] arr){
        int half = arr.length/2;
        for (int i = half; i >= 0; i--) {
            minHeapAdjust(arr, arr.length, i);
        }
    }

    private static void minHeapAdjust(int[] arr, int heapSize, int index) {
        int left = index * 1;
        int right = index * 2 + 1;
        int small = index;
        if (left < heapSize && arr[left] < arr[index]) {
            small = left;
        }
        if (right < heapSize && arr[right] < arr[small]) {
            small = right;
        }

        // 当前子树最大值不在当前根结点
        if (index != small){
            // 交换两个数据
            swap(arr,index,small);
            maxHeapAdjust(arr, heapSize, small);
        }
    }

    private static void maxHeapAdjust(int[] a, int heapSize, int index) {
        int left = index * 2;
        int right = index * 2 + 1;
        int largest = index;

        if (left < heapSize && a[left] > a[index]) {
            largest = left;
        }
        if (right < heapSize && a[right] > a[largest]) {
            largest = right;
        }

        // 当前子树最大值不在当前根结点
        if (index != largest){
            // 交换两个数据
            swap(a,index,largest);
            maxHeapAdjust(a, heapSize, largest);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

 

堆排序是一种常见的排序算法,具有稳定性高、效率高等优点。下面介绍一下使用Java实现的小根堆排序。 首先,我们需要定义一个小根堆类,用于存储待排序的数据。该类需要包含以下几个方法: 1. `Heap()`:构造函数,用于初始化小根堆。 2. `insert(int val)`:插入操作,将一个新的元素插入到小根堆中。 3. `deleteMin()`:删除操作,删除小根堆中的最小元素,并返回该元素的值。 4. `size()`:获取小根堆中元素的个数。 5. `isEmpty()`:判断小根堆是否为空。 接下来,我们就可以使用小根堆对待排序的数据进行排序了。具体的步骤如下: 1. 将待排序的数据存入小根堆中。 2. 依次从小根堆中删除最小元素,并将其存入数组中。 3. 最后,将数组反转,即可得到排序后的结果。 下面是具体的Java代码实现: ```java public class HeapSort { public static void heapSort(int[] arr) { Heap heap = new Heap(arr.length); for (int i = 0; i < arr.length; i++) { heap.insert(arr[i]); } for (int i = 0; i < arr.length; i++) { arr[i] = heap.deleteMin(); } // 反转数组 reverse(arr); } // 反转数组 private static void reverse(int[] arr) { int left = 0; int right = arr.length - 1; while (left < right) { int temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; left++; right--; } } // 小根堆类 static class Heap { private int[] heap; private int size; public Heap(int capacity) { heap = new int[capacity + 1]; size = 0; } public void insert(int val) { if (size == heap.length - 1) { throw new RuntimeException("Heap is full"); } int i = ++size; while (i != 1 && val < heap[i / 2]) { heap[i] = heap[i / 2]; i /= 2; } heap[i] = val; } public int deleteMin() { if (isEmpty()) { throw new RuntimeException("Heap is empty"); } int min = heap[1]; int last = heap[size--]; int i = 1; int child = 2; while (child <= size) { if (child < size && heap[child] > heap[child + 1]) { child++; } if (last > heap[child]) { heap[i] = heap[child]; i = child; child *= 2; } else { break; } } heap[i] = last; return min; } public int size() { return size; } public boolean isEmpty() { return size == 0; } } } ``` 使用该算法对数组进行排序: ```java int[] arr = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}; HeapSort.heapSort(arr); System.out.println(Arrays.toString(arr)); // 输出 [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9] ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值