Heap Sorting/JAVA for Algorithms

0.5 Priority Queue and Heap Sorting

  • What is a priority queue?A priority queue is a data structure that supports deleting the largest (or smallest) and inserting elements, and it works well in such cases.We have a huge amount of data and inputs, and we don't need to sort all the elements, we just need to know the largest.A typical application is to simulate systems and task scheduling. In task scheduling, we don't need to sort all tasks. We just need to know the element that has the longest waiting time and execute it. In this case, the number of inputs can't be determined or even infinite.

Let's start with a scenario where we have a data model for scientific experiments, where we have thousands of machines running and outputting data, and we just need to find the largest of them, so we need an algorithm that takes less time to insert and delete (output).

Let's compare the time of each data structure below

data structure Insert Element Delete the largest element
Ordered Array N 1
Unordered Array 1 N
heap logN logN

Thus, heap should be the best data structure in our case.What is a heap?A heap can generally be viewed as an array object of a fully binary tree, where each node is greater than or equal to two of its children and is called heap ordering.When an ordered heap is stored in an array, it has the following structure.

From the figure above, we can easily see that when the bit 0 of my tender array does not store data, we can easily abstract it into a heap, where:

  • The parent of the kth child node is k/2
  • The child node of the kth parent node is 2k+1 or 2k+2

We already know the concept of heap, so how do we turn an element into a heap order again if we change it?

  1. Bottom-up heap ordering

If a node becomes larger than its parent, we only need to swap it with its parent to repair it.

You can see that our ordering process is very simple.So how does the algorithm work?

/**
  * Sort heaps from bottom to top
  * @param k Changed Elements
  */
public static void swim(int k){
  //Keep swapping K and k/2 as long as the changed element is not the first one and is larger than k/2
  while (k > k/2 && k > 1) {
    exch(k/2, k );
    k = k/2;

  }
}
  1. Top-down heap ordering

With the experience of bottom-up ordering, top-down heap ordering is easy to understand. When a node becomes smaller than its children, we can exchange it with the largest of its two children, but we need to be careful not to cross the boundary.

The code is as follows:

public static void sink(int k){
  //As long as the child node exists
  while (2*k <= N){
    //Define Temporary Variable Settings Child Node
    int j = 2*k;
    //If the left subnode is smaller than the right subnode, it becomes the right subnode
    if (j < N && less(j,j+1)){
      j++;
    }
    //Jump out if child node is larger than itself
    if (less(j,k)){
      break;
    }
    exch(k,j);
    k = j;
  }
}

0.5.1 heap sorting

Heap sorting can be divided into two phases, where we reorganize the original array into one heap and then order the heap.Then all the elements are taken out of the heap in a descending order to get the result (each time the root node is taken out, then the heap is ordered so that the array is sorted back and forth).

  • Because above we built the heap from the first, but in our practical applications, arrays store data from 0, so we need to change the ordering method a little.The following:
/**
     * Because the heap has the current node K and the parent k/2 since the beginning of the array
     * But our array starts with 0, so we're going to dummy 0 to 1
     * The way is to add 0+1
     * But then the fourth digit of our virtual array actually exists in the third digit of the real array
     * So j-1 has to be taken to the right value
     * @param a
     * @param k
     * @param N
     */
    public static void sink(Comparable[] a,int k,int N){
        //As long as the child node exists
        while (2*(k+1) <= N){
            //Define Temporary Variable Settings Child Node
            int j = 2*(k+1);
            //If the left subnode is smaller than the right subnode, it becomes the right subnode
            if (j+1 <= N && less(a[j-1],a[j])){
                j++;
            }
            //Jump out if child node is larger than itself
            if (less(a[j-1],a[k])){
                break;
            }
            exch(a,k,j-1);
            k = j-1;
        }
    }
  • The heap sorting algorithm is as follows
public class Heap {
    /**
     * Specific algorithm implementation
     */
    public static void sort(Comparable[] a) {

        int N = a.length;
        for (int k = N/2; k >= 0; k--) {
            sink(a,k,N);
        }

        /**
         * Swap the tenth and last, and then swap the heap length -1
         * Then order the heap
         */
        while (N >= 1){
            exch(a,0 ,N-1);
            N--;
            sink(a,0,N);
        }
    }

    /**
     * Because the heap has the current node K and the parent k/2 since the beginning of the array
     * But our array starts with 0, so we're going to dummy 0 to 1
     * The way is to add 0+1
     * But then the fourth digit of our virtual array actually exists in the third digit of the real array
     * So j-1 has to be taken to the right value
     * @param a
     * @param k
     * @param N
     */
    public static void sink(Comparable[] a,int k,int N){
        //As long as the child node exists
        while (2*(k+1) <= N){
            //Define Temporary Variable Settings Child Node
            int j = 2*(k+1);
            //If the left subnode is smaller than the right subnode, it becomes the right subnode
            if (j+1 <= N && less(a[j-1],a[j])){
                j++;
            }
            //Jump out if child node is larger than itself
            if (less(a[j-1],a[k])){
                break;
            }
            exch(a,k,j-1);
            k = j-1;
        }
    }

    /**
     * Compare two elements and return true if v<w
     * @param v
     * @param w
     * @return
     */
    private static boolean less(Comparable v ,Comparable w){
        /**
         * compareTo Method
         * Returns a positive number for v>w, a negative number for v<w, and a return of 0 for v==w
         */
        return v.compareTo(w) < 0;
    }

    /**
     * Exchange a[i] and a[j]
     * @param a
     * @param i
     * @param j
     */
    private static void exch(Comparable[] a, int i, int j){
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

    /**
     * Output Array
     * @param a
     */
    private static void show(Comparable[] a){
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }

    /**
     * Test if the array is ordered
     * @param a
     * @return
     */
    private static boolean isSort(Comparable[] a){
        for (int i = 0; i < a.length; i++) {
            if (less(a[i],a[i-1])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Principal function
     * @param args
     */
    public static void main(String[] args) {
        String[] a = {"5","3","6","5","7","9","2","1","3","8"};

        sort(a);
        assert isSort(a);
        show(a);
    }

}

Characteristic:

  • The efficiency of heap sorting reaches the peak of the efficiency of comparison-based sorting algorithms
  • Time complexity is O(nlogn)
  • Only O(1) auxiliary space is required
  • Worst case time complexity is still O(nlogn)
  • Stable sorting algorithm

Tags: less

Posted on Fri, 19 Jun 2020 21:43:44 -0400 by Hell Toupee