Insertion Sort and Hill Sort Java Implementation and Comparison of Actual Efficiency

Java implementation of insertion sort and its improved Hill sort and actual performance comparison

A brief introduction to Insertion Sort and Hill Sort, as well as the Java implementation, and then a brief analysis of the time complexity and actual performance of the two

Insertion sort:

Generally, it starts from the second element of the array (subscript 1), and the elements before this element are required to be kept in order. For the specific definition, refer to Baidu Encyclopedia

Here is a simple diagram to show it:

 

 

Hill sort:

Sorting with a step size where the last step of the step size is always 1

It can be considered that the ordinary insertion sort is the last step of the Hill sort, but because the Hill sort has adjusted the order of most of the elements before the last step, the relatively time-consuming exchange assignment operation is much less than that of the insertion sort.

Not only in the last step, but in general Hill sort is faster than insertion sort, with fewer swap assignments.

It can be seen in later tests that when the amount of data exceeds 10,000, the efficiency of insertion sort is far less than that of Hill sort

The specific principle and implementation reference of Hill sorting:

Hill sort

 

Java Implementation of Insertion Sort and Hill Sort

Insertion sort:

package com.ryo.algorithm.sort;

/**
 * Insertion sort
 * @author shiin
 */
public class InsertionSort implements Sort{
	
	@Override
	public int[] sort(int[] arr) {
		int temp ;
		int j;
		for(int i=1 ;i<arr.length ;i++) {
			temp = arr[i];
			j = i-1;
			//This should be written as strong and otherwise the second judgment will throw an outofindex exception when j=-1
			while(j > -1 && arr[j] > temp) {
				arr[j+1] = arr[j];
				j--;
			}
			arr[j+1] = temp;
		}
		return arr;
	}

}

Hill sort:

package com.ryo.algorithm.sort;

/**
 * The length of the default array here will be greater than 37
 * @author shiin
 *
 */
public class ShellSort implements Sort{
	
	//step sequence
	private int[] steplist = {373,181,83,37,17,7,3,1};

	@Override
	public int[] sort(int[] arr) {
		//input array length
		int len = arr.length;
		// Perform sub-sort times
		int times = 0;
		//current step
		int step;
		// temporary storage variable
		int temp;
		// temporary storage index
		int m;
		for(;times < steplist.length ;times++) {
			step = steplist[times];
			//here i is equivalent to an offset, the maximum offset cannot exceed the step size
			for(int i=0 ;i<step ;i++) {
				//j,j+step,j+2*step... is the subscript that is divided into a group
				//Starting here is similar to direct insertion sorting, it can be considered that the step of direct insertion sorting is 1
				for(int j=i ;j<len &(j+step)<len;j=j+step) {
					temp = arr[j+step];
					m = j;
					while(m > -1 && arr[m] > temp) {
						arr[m+step] = arr[m];
						m = m-step;
					}
					arr[m+step] = temp;
				}
			}
		}
		return arr;
	}
}

Class for testing:

packagecom.ryo.algorithm.sort;
 
import com.ryo.algorithm.util.Util;
 
public class DoSort {
    
    private int[] result = new int[20000];
 
    public static void main(String[] args) {
       DoSort ds = new DoSort();
       long before = System.currentTimeMillis();
       
       //Replace the method that needs to be tested in this line
       ds.testShellSort();
       
       long after = System.currentTimeMillis();
       for(intn : ds.getResult()) {
           System.out.println(n);
       }
       System.out.println("total time : "+(after-before)+"ms");
    }
    
    public DoSort() {
       for(inti=0 ;i<result.length ;i++) {
           //Here is the written method to randomly create 0-10000 random numbers
           result [i] = Util.random ();
       }
    }
    
    public void testInsertionSort() {
       new InsertionSort().sort(result);
    }
    
    public void testShellSort() {
       new ShellSort().sort(result);
    }
    
    public int[] getResult() {
       return this.result;
    }
 
}

Performance comparison:

Test environment: Jdk 1.8.0_161 eclipse Version: Oxygen.3a Release (4.7.3a)

Test data: The length of the array is 20000, and there are random integers from 0 to 20000. Run several times in advance to stabilize the running time, and then take the average of three runs. Additional operations such as initialization are not within the timing range.

Runtime result:

Insertion sort

   

Average time: 147ms

Hill sort

  

Average time: 7ms

In fact, because the maximum step size taken here is 373, the running time of taking a few more steps will be smaller. The value of the step size directly affects the efficiency of Hill sorting, and the impact is very large.

Here, on the basis of private int [] steplist ={373,181,83,37,17,7,3,1}; add a 733 and 1607 , and then run it and find that the time can be basically stable at 6ms

From the comparison of the results here, we can see that when the amount of data exceeds 10,000, the efficiency of Hill sorting is far greater than that of direct insertion sorting. If the amount of data continues to increase, the time required for insertion sorting will increase faster.

 

About the time complexity of direct insertion sort and Hill sort

The average time complexity of direct insertion sort is O(n^2), the time complexity in the best case (that is, sorted) is O(n), and the time complexity in the worst case (that is, in reverse order) is O(n^2)

The average time complexity of Hill sort should be close to O(n^1.3) when choosing a better step size, and the worst and optimal time complexity is the same as direct insertion sort

Since the efficiency of Hill sorting is closely related to the step size of program selection, the research on the step size selection of Hill sorting is actually a mathematical problem

Compare the actual efficiency in this program:

Theoretical efficiency multiple: 20000^2 / 20000^1.3 = 1025

Actual efficiency multiple: 147 / 7 = 21

1025 >> 21

Since 1025 is only a multiple of theoretical efficiency, but because only the main time-consuming operations are included in the calculation of time complexity, some non-critical operations directly consider the time-consuming to be 0, and there are also influences such as Java environment and memory access, resulting in numerical values big deviation

But we can still see that there is a large gap between the actual efficiency of the two algorithms

 

 

Guess you like

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