Sorting (2) Insert sorting c / c ++ and python implementation

Insert sort

The basic idea of ​​insertion sorting : insert a sequence to be sorted into the subsequences that have been sorted according to its key size each time, and know that all records are inserted. There are direct insertion sorting, halved insertion sorting and Hill sorting.

Straight Insertion Sort

The basic idea of ​​direct insertion sorting : First, we divide the data in the array into two intervals, the sorted interval and the unsorted interval. The initial sorted interval has only one element, which is the first element of the array. The core idea of ​​the direct insertion algorithm is to take the first element in the unsorted interval, find a suitable insertion position in the sorted interval and insert it, and ensure that the data in the sorted interval is always ordered. This process is repeated until the elements in the unsorted interval are empty and the algorithm ends.

//	直接插入排序c实现,a表示数组,n表示数组大小
/**
 * Author: gamilian
*/
void straight_insertion_sort(int a[], int n) {
	if (n <= 1) 
		return;

  	for (int i = 1; i < n; ++i) {
  		int value = a[i];
    	int j = i - 1;
    	// 查找插入的位置
    	for (; j >= 0; --j) {
      		if (a[j] > value) 
        		a[j+1] = a[j];  // 数据移动
      		else 
        		break;
      
    	}
    	a[j+1] = value; // 插入数据
  	}	
}
# 直接排入排序python实现
"""
    Author: gamilian
"""
def straight_insertion_sort(a):
    """ 直接插入排序
        args:
            a: List[int]
    """
    length = len(a)
    if length <= 1:
        return
    for i in range(1, length):
        value = a[i]
        j = i-1
        while j >= 0:
            if a[j] > value:
                a[j + 1] = a[j]
            else:
            	break
            j -= 1
        a[j + 1] = value

The stability of the algorithm : In the direct insertion sort, for the elements with the same value, we can choose to insert the elements that appear later after the elements that appear in the front, so that the original order can be maintained unchanged, so the direct insertion sort Is a stable sorting algorithm.

Space complexity : It can be clearly seen from the implementation process that the direct insertion sort algorithm does not require additional storage space, so the space complexity is O (1), that is, this is an in-place sort algorithm .

Time complexity : If the data to be sorted is already ordered, we do not need to move any data. If we look for the insertion position in the ordered data group from end to end, we only need to compare one data at a time to determine the insertion position. So in this case, the time complexity is preferably O (n) . Note that here is traversing the already ordered data from end to end. If the array is in reverse order, each insertion is equivalent to inserting new data at the first position of the array, so a large amount of data needs to be moved, so the worst-case time complexity is O (n ^ 2) . The average time complexity of inserting a data in the array is O (n). Therefore, for direct insertion sorting, each insertion operation is equivalent to inserting a data into the array, and performing n insertion operations in a loop, so the average time complexity is O (n ^ 2) .

Binary Insertion Sort (Binary Insertion Sort)

The basic idea of ​​binary insertion sorting : Direct insertion sorting needs to first find out the insertion position of the element to be inserted, and then make room for the insertion position to insert the element to be inserted. We move through the insertion to achieve the above operation. Binary insertion sorting separates the operation of searching for the insertion position and moving the element. First, the binary search is performed to find out the position of the element to be inserted, and then all elements after the position to be inserted are moved uniformly.

//	二分插入排序c实现,a表示数组,n表示数组大小
/**
 * Author: gamilian
*/
void binary_insertion_sort(int a[], int n){
	int i, j, left, right;
	if (n <= 1)
		return;
	for (int i = 1; i < n; ++i)	
	{
		int value = a[i];
		int j = i -1;
		left = 0;
		right = i;
		while (left < right){	//二分查找插入位置最终left为插入位置
			int mid = left + (right - left) / 2;	//防止整形溢出
			if (a[mid] < value)
				left = mid + 1; //下一轮搜索区间是 [mid + 1, right]
			else if (a[mid] == value){
				left = mid + 1;	//相同值插入到后面,保持算法稳定性
				break;
			}
			else
				right = mid;
		}
		for(; j >= left; --j)
			a[j + 1] = a[j];	//统一移动元素,空出插入位置
		a[left] = value;
	}
}
# 二分排入排序python实现
"""
    Author: gamilian
"""
def binary_insertion_sort(a):
    """ 二分插入排序
        args:
            a: List[int]
    """
    length = len(a)
    if length <= 1:
        return
    for i in range(1, length):
        value = a[i]
        j = i - 1
        left = 0
        right = i
        while left < right:
            mid = (left + right) >> 1
            if a[mid] < value:
                left = mid + 1
            elif a[mid] == value:
                left = mid -1
            else:
                right =mid
        while j >= left:
            a[j + 1] = a[j]
            j -= 1
        a[left] = value

The stability of the algorithm : In binary insertion sorting, for elements with the same value, we can choose to insert the elements that appear later after the elements that appear in front, so that the original order can be maintained unchanged, so binary insertion sorting Is a stable sorting algorithm.

Space complexity : It can be clearly seen from the implementation process that the binary insertion sort algorithm does not require additional storage space, so the space complexity is O (1), that is, this is an in-place sort algorithm .

Time complexity : The number of binary insertion sorted element comparisons has nothing to do with the initial state of the array to be sorted, which depends on the number of elements n, about nlogn times, but the number of element movements has not changed, depending on the initial state of the array to be sorted . If the data to be sorted is already ordered, we do not need to move any data. So in this case, the best time complexity is O (nlogn) . If the array is in reverse order, each insertion is equivalent to inserting new data at the first position of the array, so a large amount of data needs to be moved, so the worst-case time complexity is O (n ^ 2) . The average time complexity of inserting a data in the array is O (n). Therefore, for binary insertion sorting, each insertion operation is equivalent to inserting a data into the array, and performing n insertion operations in a loop, so the average time complexity is O (n ^ 2) .

For cases where the amount of data is not very large, binary insertion sorting often performs better than direct insertion sorting.

Hill Sort

The basic idea of ​​Hill sorting : also called descending incremental sorting algorithm, which splits the entire sequence according to an "incremental" distance, and then directly inserts and sorts the subsequences one by one, so that the obtained results are basically ordered, and finally The basic ordered sequence is directly inserted and sorted once, so that the entire sequence is ordered.
The main steps of the algorithm are as follows :

  1. Select an initial length d1, divide the original sequence into several regions, and insert and sort each region separately
  2. After the first step is completed, the step length is half, and then the sequence sorted in the first step is divided into several areas, and the insertion sort is performed separately.
  3. By analogy, until the step size is 1, the sequence is almost sorted in ascending order at this time, and then insertion sorting is performed (insert sorting is for sequences that are almost already sorted, which is highly efficient)
//	希尔排序c实现,a表示数组,n表示数组大小
/**
 * Author: gamilian
*/
void shell_sort(int a[], int n){
	for (int d = n / 2; d >= 1; d /= 2)	//拆分整个序列,元素间距为d(也就是增量)
		for (int i = d ; i < n; i++){	//子序列直接插入排序
			int value = a[i];
			int j = i - d;
			for (; j >= 0 ;j -= d){	
				if (a[j] > value)
					a[j + d] = a[j];
				else
					break;
			}
			a[j + d] = value;
		}
}
# 希尔排序python实现
"""
    Author: gamilian
"""
def shell_sort(a):
    """ 希尔排序 
        args:
            a: List[int]
    """
    length = len(a)
    if length <= 1:
        return

    d = length // 2  # 初始步长
    while d > 0:  
    # 最后一次步长为1(即普通的插入排序),然后整个希尔排序结束
        # 普通的插入排序算法中步长是 1 ,把插入排序中的步长 1 替换为d
        for i in range(d, length):
            value = a[i]
            j = i - d
            while j >= 0:
                if value < a[j]:
                    a[j + d] = a[j]
                else:
                    break
                j -= d
            a[j + d] = value
        # 得到新的步长
        d = d // 2 

Stability of the algorithm : Although a direct insertion sort is stable and does not change the relative order of the same elements, multiple direct insertion sorts are required. In different direct insertion sort processes, elements of the same value are divided into different sub The sequence may change their relative order, and eventually their stability will be disrupted, so Hill sorting is unstable .

Space complexity : It can be clearly seen from the implementation process that the direct insertion sort algorithm does not require additional storage space, so the space complexity is O (1), that is, this is an in-place sort algorithm .

Time complexity : the best-case time complexity is O (n) , and the worst-case time complexity is O (n ^ 2) . When n is in a certain range, the time complexity of Hill sorting is about O (n ^ 1.3) .

Published 10 original articles · Likes2 · Visits 496

Guess you like

Origin blog.csdn.net/qq_41167295/article/details/105138872