孤樱懶契 发表于 2021-6-30 15:12

【Java】数据结构-堆排序(完整代码)

本帖最后由 孤樱懶契 于 2021-10-23 22:40 编辑

# 堆排序和其他排序算法时间复杂度比较截图

!(https://gitee.com/gylq/cloudimages/raw/master/img/image-20210630150821902.png)

# 堆排序执行(完整代码)

## MaxHeap.java(最大堆数据结构)

```java
public class MaxHeap<E extends Comparable<E>> {

    private Array<E> data;

    public MaxHeap(int capacity){
      data = new Array<>(capacity);
    }

    public MaxHeap(){
      data= new Array<>();
    }

    // 返回堆中的元素个数
    public int size(){
      return data.getSize();
    }

    // 返回一个布尔值,表示堆中是否为空
    public boolean isEmpty(){
      return data.isEmpty();
    }

    // 返回完全二叉树的数组表示中,一个索引所表示的元素的父亲节点的索引
    private intparent(int index){
      if(index == 0)
            throw new IllegalArgumentException("index-0 doesn't have parent.");
      return (index - 1) / 2;
    }

    // 返回完全二叉树的数组表示中,一个索引所表示的元素的左孩子节点的索引
    private int leftChild(int index){
      return index * 2 + 1;
    }

    // 返回完全二叉树的数组表示中,一个索引所表示的元素右孩子节点的索引
    private int rightchild(int index){
      return index * 2 + 2;
    }

    // 向堆中添加元素
    public void add(E e){
      data.addLast(e);
      siftUp(data.getSize()- 1);
    }

    private void siftUp(int k){

      while(k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0 ){
            data.swap(k , parent(k));
            k = parent(k);
      }
    }

    // 看堆中的最大元素
    public E findMax(){
      if(data.getSize()==0)
            throw new IllegalArgumentException("can not findMax when heap is empty!");
      return data.get(0);
    }

    // 取出堆中最大元素
    public E extractMax(){

      E ret = findMax();

      data.swap(0, data.getSize()-1);
      data.removeLast();
      siftDown(0);

      return ret;
    }

    private void siftDown(int k ){

      while(leftChild(k) < data.getSize() ){

            int j = leftChild(k);
            if(j + 1 < data.getSize() && data.get(j+1).compareTo(data.get(j))>0){
                j = rightchild(k);
            }
            //data 是左右孩子中最大值

            if(data.get(k).compareTo(data.get(j)) >= 0)
                break;
            data.swap(k,j);
            k = j;
      }
    }
}

```

## Array.java(堆使用的自定义动态数组)

```java
public class Array<E> {

    private E[] data;
    private int size;//大小

    // 构造函数 转入数组的容量capacity构造Array
    public Array(int capacity){
      data =(E[])new Object;
      size = 0    ;
    }

    // 无参的构造函数,默认数组的容量capacity = 10
    public Array(){
      this(10); //调用有参构造函数传入10设定初始大小
    }

    // 获取数组中元素个数
    public int getSize(){
      return size;
    }

    // 获取数组的容量
    public int getCapacity(){
      return data.length;
    }

    //返回数组是否为空
    public boolean isEmpty(){
      return size == 0;
    }

    // 向所有元素后添加一个新元素
    public void addLast(E e){

//         if(size == data.length) {
//             throw new IllegalArgumentException("AddLast failed. Array is full.");
//         }
//         data = e;
//         size ++;
      add(size, e);
    }

    // 在所有元素前添加一个新元素
    public void addFirst(E e){
      add(0, e);
    }

    // 在第index个位置插入一个新元素e
    public void add(int index, E e){

      if(index < 0 || index > size ){
            throw new IllegalArgumentException("Add failed. Require index >=0 and index <= size.");
      }

      if(size == data.length) {
            resize(2 * data.length);
      }

      for(int i = size - 1 ; i >= index ; i--){
            data=data;
      }
      data = e;
      size ++;
    }

    // 获取index索引位置的元素
    public E get(int index){
      if(index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Index is illegal.");
      return data;
    }

    // 修改index索引位置的元素为e
    public void set(int index, E e){
      if(index < 0 || index >= size)
            throw new IllegalArgumentException("set failed. Index is illegal.");
      data = e;

    }

    // 查找数组中是否有元素e
    public boolean contains(E e){
      for(int i = 0 ; i < size ; i++)
      {
            if(data.equals(e))
                return true;
      }
      return false;
    }

    // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
    public int find(E e){
      for(int i = 0 ; i < size ; i++)
      {
            if(data.equals(e))
                return i;
      }
      return -1;
    }

    // 从数组中删除index位置的元素,返回删除的元素
    public E remove(int index){
      if(index < 0 || index >= size)
      {
            throw new IllegalArgumentException("Remove failed. Index is illegal.");
      }
      E ret = data;
      for(int i = index + 1 ; i < size ; i ++)
      {
            data = data;
      }
      size --;
      data = null; //让他自动回收 非必须写loitering objects != memory leak

      if(size == data.length / 4 && data.length / 2 != 0)
            resize(data.length / 2);
      return ret;
    }

    // 从数组中删除第一个元素,返回删除的元素
    public E removeFirst(){
      return remove(0);
    }

    // 从数组中删除最后一个元素,返回删除的元素
    public E removeLast(){
      return remove(size-1);
    }

    // 从数组中删除元素e
    public void removeElement(E e){
      int index = find(e);
      if(index != -1)
            remove(index);
    }

    public void swap(int i , int j){

      if(i < 0 || i >= size || j < 0 || j >= size)
            throw new IllegalArgumentException("Index is illegal.");

      E t = data;
      data = data;
      data = t;
    }

    //system.out.print()所输出的类型toString覆盖
    @Override
    public String toString(){

      StringBuilder res = new StringBuilder();
      res.append(String.format("Array: size = %d, capacity = %d \n", size, data.length));
      res.append('[');
      for(int i = 0 ; i < size ; i ++){
            res.append(data);
            if(i != size - 1)
                res.append(", ");
      }
      res.append(']');
      return res.toString();
    }

    private void resize(int newCapacity){
      E[] newData = (E[])new Object;
      for(int i = 0 ; i < size ; i ++)
            newData = data;
      data = newData;
    }
}

```

## SortingHelper.java(辅助进行算法时间输出的)

```java
public class SortingHelper {

    private SortingHelper(){} //私有类

    public static <E extends Comparable<E>> boolean isSorted(E[] arr){

      for(int i = 1; i< arr.length; i++)
            if (arr.compareTo(arr) > 0)
            return false;
      return true;
    }

    public static <E extends Comparable<E>> void sortTest(String sortname, E[] arr){
      long startTime = System.nanoTime();
      if(sortname.equals("SelectionSort")) {
            SelectionSort.sort(arr);
      } else if(sortname.equals("InsertionSort"))
            InsertionSort.sort(arr);
      else if(sortname.equals("InsertionSort2"))
            InsertionSort.sort2(arr);
      else if(sortname.equals("MergeSort"))
            MergeSort.sort(arr);
      else if(sortname.equals("MergeSort2"))
            MergeSort.sort2(arr);
      else if(sortname.equals("MergeSort3"))
            MergeSort.sort3(arr);
      else if(sortname.equals("MergeSort4"))
            MergeSort.sort4(arr);
      else if(sortname.equals("MergeSortBU"))
            MergeSort.sortBU(arr);
      else if(sortname.equals("QuickSort"))
            QuickSort.sort(arr);
      else if(sortname.equals("QuickSort2"))
            QuickSort.sort2ways(arr);
      else if(sortname.equals("QuickSort3"))
            QuickSort.sort3ways(arr);
      else if(sortname.equals("HeapSort"))
            HeapSort.sort(arr);
      long endTime = System.nanoTime();

      double time = (endTime - startTime) / 1000000000.0; //纳米要/9个零

      if(!SortingHelper.isSorted(arr))
            throw new RuntimeException(sortname + "failed");
      System.out.println(String.format("%s , n = %d : %f s ", sortname, arr.length, time));
    }
}

```

## ArrayGenerator.java(生成随机的一组数组或有序的一组数组)

```java
import java.util.Random;

public class ArrayGenerator {

    private ArrayGenerator(){}

    public static Integer[] generateOrderedArray(int n){

       Integer[] arr = new Integer;
       for(int i = 0; i < n ; i++)
         arr = i;
       return arr;
    }

    // 生成一个长度为 n 的随机数组, 每个数字的范围是[ 0 , bound)
    public static Integer[] generateRandomArray(int n, int bound){

      Integer[] arr = new Integer;
      Random rnd = new Random();
      for(int i = 0 ; i < n; i++)
            arr = rnd.nextInt(bound); //从0到bound前闭后开
      return arr;
    }
}

```



## HeapSort.java(简单的堆排序)

> 因为是最大堆,所以进行了逆置输出

```java
import java.util.Arrays;

public class HeapSort {

    private HeapSort(){}

    public static <E extends Comparable<E>> void sort(E[] data){

      MaxHeap<E> maxHeap = new MaxHeap<>();
      for(E e: data)
            maxHeap.add(e);

      for(int i = data.length - 1 ; i >= 0 ; i --)
            data = maxHeap.extractMax();
    }

    public static void main(String[] args) {

      int n = 1000000;

      Integer[] arr = ArrayGenerator.generateRandomArray(n , n);
      Integer[] arr2 = Arrays.copyOf(arr, arr.length);
      Integer[] arr3 = Arrays.copyOf(arr, arr.length);
      Integer[] arr4 = Arrays.copyOf(arr, arr.length);
      Integer[] arr5 = Arrays.copyOf(arr, arr.length);

      sort(arr5);

      for(int i = 0 ; i < n ; i ++){
            System.out.println(arr5);
      }

      SortingHelper.sortTest("MergeSort", arr);
      SortingHelper.sortTest("QuickSort2", arr2);
      SortingHelper.sortTest("QuickSort3", arr3);
      SortingHelper.sortTest("HeapSort", arr4);
    }
}

```


xfmiao 发表于 2021-6-30 16:27

楼主的编辑器用的哪个的,不像pycharm

lvbuqing 发表于 2021-6-30 17:55

xfmiao 发表于 2021-6-30 16:27
楼主的编辑器用的哪个的,不像pycharm

IntelliJ IDEA

与影立黄昏 发表于 2021-6-30 20:12

idea哪个版本啊 我安装一次太卡了
页: [1]
查看完整版本: 【Java】数据结构-堆排序(完整代码)