Algorithms - Quick Sort, Hill Sort, Heap Sort

The previous article Simple Algorithms - Direct Insertion, Bubbling, and Direct Selection introduced the simple sorting method. Based on the previous article, this article introduces the advanced algorithms corresponding to each simple sorting method.
The first is still to do a public element replacement function

/**
     * 交换数组元素
     * 交换思想很简单 数字x y  =>  x=x+y;y=x-y;x=x-y;
     * 这种方法不使用临时变量,能有效降低算法空间复杂度,但也有缺点,比如可能存在越界风险
     * @param arr
     * @param a
     * @param b
     */
    public void swap(int []arr,int a,int b){
        arr[a] = arr[a]+arr[b];
        arr[b] = arr[a]-arr[b];
        arr[a] = arr[a]-arr[b];
    }

quicksort

Quicksort is an improvement on bubble sort.
Basic idea: The first pass divides the data into two parts, and all the data in one part is smaller than the other part, and then quickly sorts the two parts of the data according to this method. The whole sorting process can be recursively performed until the entire The data becomes an ordered sequence.
Basic operations:
1. Set two variables i, j, when sorting starts: i=0, j=n-1;
2. Use the first array element as the key data and assign it to the key, that is, key=A[0 ];
3. Search forward from j, that is, search forward (j–) from the back, find the first value A[j] less than the key, and exchange A[j] and A[i];
4 , Search backward from i, that is, search backward from front (i++), find the first A[i] greater than key, and exchange A[i] and A[j];
5. Repeat the 3rd, 4 steps until i=j;
such as:
original array [5, 3, 6, 4, 8, 7, 9]
First round of quick sort:
According to basic operations 1, 2: set variables key=5, i=0, j=7
According to basic operation 3, operation j gets: 4 3 6 5 8 7 9 (i=0, j=3, a[j]=5, a[i]=4)
According to basic operation 4, operation i gets : 4 3 5 6 8 7 9 (i=2,j=3,a[i]=5,a[j]=6)
According to basic operation 3, operation j, when j is equal to 2, it is found that i==j, and the first quick sort ends at this time. At this time, we get: 4 3 5 6 8 7 9 Find all the values ​​larger than key(6) All are on the right, and those smaller than the key are all on the left!

Then, for the data on both sides of the key, the above process is performed separately until it can no longer be grouped.
Code:

    int arr[] = {5, 3, 6, 4, 8, 7, 9};
    quickSort(arr,0,arr.length-1);
    public void quickSort(int[] arr, int low, int high){
         if(low >= high) {
            return;
        }
        System.out.print(" k = " + ++k);
        //基本操作1、2
        int i = low;
        int j = high;
        int key = arr[low];
        while (i<j){
            //基本操作3
            while (i < j && arr[j] >= key){
                j--;
            }
            if(i < j) {
                swap(arr, i++, j);
            }

            //基本操作4
            while (i < j && arr[i] < key){
                i++;
            }
            if(i < j) {
                swap(arr, i, j--);
            }
        }
        //对key两边的数据,再分别进行上述的过程
        quickSort(arr,low,i-1);
        quickSort(arr,i+1,high);
    }

There are many variants of quick sort, such as three-average partition method, randomized quick sort, etc. I won't introduce it here!

Hill sort

Shell's Sort is a more efficient and improved version of the direct insertion sorting algorithm.
The basic idea: first take a positive integer d1 < n as the first increment, group all data pairs separated by d1 in the array into a group, and perform direct insertion sorting in the group; then take d2 < d1, and repeat the above operations until di = 1, that is, until all records are placed in the same group for direct insertion sorting. (Generally d1=n/2, halved each time in the future, if the result is an even number, add 1 to ensure that the subsequent increment is an odd number).

The original array 5,3,6,4,8,7,9 The
first step: d1 takes 3, divides the data separated by 3 into a group, and performs direct insertion sorting in the group
[5,4,9] [3, 8] [6,7] —> 4 3 6 5 8 7 9
The second step: d2=1, divide the data separated by 1 into a group, and perform direct insertion sorting in the group
[5,3,6,4, 8,7,9] —> 3 4 5 6 7 8 9

Code

   int arr[] = {5, 3, 6, 4, 8, 7, 9};
   public void sort(int[] arr) {
        //增量gap,并逐步缩小增量
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            //从第gap个元素,逐个对其所在组进行直接插入排序操作
            directSort(arr, gap);
        }
    }

    //这里就是简单插入排序了,详细可查看上一篇文章
    public void directSort(int[] arr, int gap) {
        for (int i = 0; i < arr.length; i++) {
            int j = i;
            while (j + gap <=arr.length-1 && arr[j] > arr[j + gap]){
                swap(arr, j, j + gap);
                j += gap;
            }
        }
    }

heap sort

Heapsort (Heapsort) refers to a sorting algorithm designed using the data structure of a stacking tree (heap), which is a kind of selection sort. You can use the characteristics of the array to quickly locate the element at the specified index. The heap is divided into a large root heap and a small root heap, which is a complete binary tree.
Small root heap: arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]; large root heap: arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] . This article takes the big root heap (ascending order) as an example!
Basic operations:
①Building a heap: Building a heap is a process of continuously adjusting the heap, starting from len/2 to the first node;
②Adjusting the heap: Adjusting the heap is to compare the node i and its child node left(i), right(i), select the largest (or smallest) of the three, if the largest value is not node i but a child node of it, exchange it, and then repeat the process.
③ Heap sort: Heap sort is performed using the above two processes. The root node is taken out first, then the first len-1 nodes continue the process of heap adjustment, and then the root node is taken out until all nodes are taken out.
This sorting requires a certain understanding of the "tree": the
original array [5,3,6,4,8,7,9] can be converted into the following binary tree structure
write picture description here
Program implementation

     int arr[] = {5, 3, 6, 4, 8, 7, 9};
     //构建大顶堆
     buildMaxHeapify(arr);
     //堆排序
     heapSort(arr);

    /**
     *排序,最大值放在末尾,arr虽然是最大堆,在排序后就成了递增的
     *
     *@paramarr
     */
    private static void heapSort(int[] arr){
        //末尾与头交换,交换后调整最大堆
        for(int i=arr.length-1;i>0;i--){
            swap(arr, 0, i);
            maxHeapify(arr,i,0);
        }
    }

    /**
     * 建堆
     * @param arr
     */
    private static void buildMaxHeapify(int[] arr){
        //从最后一个的父节点开始
        int startIndex=getParentIndex(arr.length-1);
        //从下至上,从右至左调整
        for(int i=startIndex;i>=0;i--){
            maxHeapify(arr,arr.length,i);
        }
    }

    /**
     *调整堆
     */
    private static void maxHeapify(int[] arr,int size,int index){
        //获取左子节点下标 等价于index*2+1
        int left = (index<<1) + 1;
        //获取右子节点下标 等价于index*2+2
        int right = (index<<1) + 2;

        //当前点与左右子节点比较
        int largest=index;
        if(left<size && arr[index]<arr[left]){
            largest=left;
        }
        if(right<size && arr[largest]<arr[right]){
            largest=right;
        }
        //得到最大值后可能需要交换,如果交换了,其子节点可能就不是最大堆了,需要重新调整
        if(largest!=index){
            swap(arr, index, largest);
            maxHeapify(arr,size,largest);
        }
    }

    /**
     *父节点位置
     *@return 等价于(current-1)/2 如:(4-1)/2等于1 等价于二进制0011向右移动一位0001
     */
    private static int getParentIndex(int current){
        return(current-1)>>1;//>>表示向右移动一位
    }

Reference
Quick Sort Algorithm
Vernacular Classic Algorithm Series
Graphical Sorting Algorithm Series
Heap Sort

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325505298&siteId=291194637