Insertion sort (direct, binary, two-way, Hill)

[Past Issue] Six Search Algorithms

[Three classic searches] jumping, interpolation, Fibonacci

[Three basic search] order, dichotomy, block 

Table of contents

[Past Issue] Six Search Algorithms

foreword

1. Stable sorting?

2. Direct insertion sort O(n^2)

1. Usage scenarios

2. Execution steps

3. Half insertion sort O(n^2)

1. Execution steps 

Four, 2-way insertion sort worst O(n^2)

5. Hill sort

1. Usage scenarios

2. Execution steps 


foreword

  Searching and sorting are an indispensable part of data structures and algorithms. They are important and convenient skills left by the predecessors on the road of algorithms. Learning these classic searching and sorting can also make us better and faster Solve the problem. In this column, we will learn about the six major searches and the top ten sorts, and this article will explain in detail the insertion sort - direct insertion sort, half (divided) insertion sort, 2-way insertion sort;

  Note: All sorts in this article are sorted in ascending order, and descending order only needs to reverse the logic!


1. Stable sorting?

Before learning the sorting algorithm, we need to understand some concepts about sorting:

  • In-place sorting: only need to use constant extra space and given array, space complexity is O(1);
  • External sorting and internal sorting: Check whether the sorted data can be loaded into memory at one time, if not, you can only use external sorting;
  • What is a stable sort? The so-called "stability": judge the change of the relative position of the same keyword before and after sorting, such as the sequence 3 2 2 5 is 2 2 3 5 after sorting, if the relative position of 2 and 2 does not change, then the sorting algorithm is stable;
  • Unstable sorting means that there are many exchanges, and if you need to sort by multiple conditions, it will be chaotic; the stability of the sorting algorithm is very important when dealing with multiple data and key-value pairs;

The concept of sorting is very simple, focus on understanding the concept of stability and go through the others;


2. Direct insertion sort O(n^2)

1. Usage scenarios

Students who have known the bottom layer of C++STL should know that in the past, the bottom layer of sort sorting used quick sorting, but quick sorting is actually an unstable sorting. Now sort uses multiple sorts to sort It has been supplemented, and this direct insertion sort is a supplement to the quick sort when the amount of data is less than 8 ;

2. Execution steps

  • Basic idea: Divide the array to be sorted into two sequences, keep the sequence in front of it in order, select the elements in the back and insert them in turn, which is in-place sorting;

An array is shown below, the first step: regard arr[0] as ordered, compare arr[0] < arr[1], and currently consider arr[1] to be ordered;

The second step: compare arr[1] > arr[2], exchange; compare arr[0] < arr[1], think that the position is correct, stop the exchange, and continue;

Step 3: compare arr[2] > arr[3], exchange; compare arr[1] > arr[2], exchange; compare arr[0] < arr[1], stop the exchange if the position is correct, and repeat the above steps;

Until all the numbers are considered in order, the sorting ends;

 The code implementation is also very simple

#include <stdio.h>
#include<stdlib.h>

//直接插入排序
void insertSort(int a[], int n)
{
    if(a == NULL)
    {
        return;
    }
        
    //将a[i]插入到a[i -1]、a[i - 2]...
    for(int i = 1; i < n; i++)
    {
        for(int j = i; j > 0 && a[j] < a[j - 1]; j--)
        {
            //后一个小于前一个 交换
            int temp = a[j];
            a[j] = a[j - 1];
            a[j - 1] = temp;
        }
    }
}

int main()
{
    int arr[] = {9, 10, 13, 20, 12};
    int length = sizeof(arr) / sizeof(arr[0]);
    insertSort(arr, length);
    for(int i = 0; i < length; i++)
    {
        printf("%d \n", arr[i]);
    }
    system("pause");
    return 0;
}

 operation result

 


3. Half insertion sort O(n^2)

The half-insertion sorting idea is the same as the half-way (two-point) search, which is the application of the half-way (two-point) search;

1. Execution steps 

  • Sequentially insert each element in the sequence to be searched into the sequence according to the size of its keyword through a half (binary) search;

have an array {0, 9, 10, 12, 20, 8, 5, 7, 1};

Take the number 8 as an example, we want to find its correct position in the array, (assuming that the sequence before the element 8 has been sorted according to the rules) we only need to follow the rules of binary search, and continuously narrow the range to be searched until The left value field low is greater than the right value field high, and the pointer mid we found at this time is the correct position in the array where the element to be sorted is located;

After finding the correct position, it is interpolation, because it cannot be directly inserted in the array, it is necessary to move all the elements between the interval [mid, i] (i is the subscript of the number to be arranged) from the back to the front;

The logic and code of the half insertion sort are very simple, the key is to learn the idea of ​​binary search and how to move elements in the array;


Four, 2-way insertion sort worst O(n^2)

The 2-way insertion sort is an improvement on the basis of the half sort, and its purpose is to reduce the number of data movements during the sorting process:

  • In addition, set a circular array D with the same size as the array to be sorted, add the first record in the unordered list to D[0], and compare it with D[0] from the second position of the unordered list. If it is greater than Add to the right and vice versa to the left;

For the knowledge of ring arrays, you can see that the idea of ​​ring queues and ring arrays in the data structure of @康laigecheng is the same;

The source code is as follows: the difficulty of the code lies in how to understand the modular operation, and it will be very clear if you draw more on paper;

#include<stdio.h>
#include<stdlib.h>

//二路插入排序
void twoWayInsert(int a[], int n, int temp[])
{
    int first, final;//分别记录temp数组的最大值和最小值
    first = final = 0;
    temp[0] = a[0];
    for(int i = 1; i < n; i++)
    {
        //插入的元素比最小的元素都要小
        if(a[i] < temp[first])
        {
            first = (first - 1 + n) % n;
            temp[first] = a[i];
        }
        //待插入的元素要比最大值还大
        else if(a[i] > temp[final])
        {
            final = (final + 1 + n) % n;
            temp[final] = a[i];
        }
        else
        {
            int k = (final + 1 + n) % n;
            //当插入的值比当前值小的时候 需要移动当前值的位置
            while(temp[((k - 1) + n) % n] > a[i])
            {
                temp[(k + n) % n] = temp[(k - 1 + n) % n];
                k = (k - 1 + n) % n;
            }
            temp[(k + n) % n] = a[i];
            //插入元素 因为最大值的位置发生了改变 所以更新最大值的下标
            final = (final + 1 + n) % n;
        }
    }
    //将元素放回原数组中
    for(int i = 0; i < n; i++)
    {
        a[i] = temp[(first + i) % n];
    }
}

int main()
{
    int arr[] = {9, 10, 13, 20, 12};
    int length = sizeof(arr) / sizeof(arr[0]);
    int* temp = (int*)malloc(sizeof(temp) * length);
    twoWayInsert(arr, length, temp);
    for (int i = 0; i < length; i++)
    {
        printf("%d ", arr[i]);
    }
    
    system("pause");
    return 0;
}

operation result 


5. Hill sort

1. Usage scenarios

  • Hill sorting is also called shrinking incremental sorting, which uses a jumping strategy to divide the array into several groups through a certain incremental gap;
  • Group the array to be sorted according to some incremental sorting of subscript records, and perform direct insertion sorting for each group. As the increment decreases, each group contains more and more keywords. When the increment decreases to 1, it will became a group;

2. Execution steps 

There is an array {8, 9, 1, 7, 2, 3, 5, 4, 6, 0}

Assume) increment gap = array length/2 = 5 ( increment selection is a complex mathematical problem, the selected increment is different, the complexity is also different ) and then directly insert and sort these groups, which is equivalent to the first time The grouped values ​​are exchanged once;

 gap = 5 / 2 = 2;

gap = 2 / 2 = 1;

 The code implementation of Hill sorting is also very simple. The key to sorting is the selection of incremental gaps :

Like for the array { 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16 } or select incremental initialization as gap = n / 2 = 8 Then, you will find that the first three sorts have not changed, that is, the worst-case complexity of this array is O(n^2), and it should be noted that the incremental elements cannot be prime numbers!

#include <stdio.h>
#include<stdlib.h>

//希尔排序
void shellSort(int a[], int n)
{
    int gap;//步长
    int k;                               
    for (gap = n / 2; gap > 0; gap/=2) //步长的选取
    {
        //直接插入排序
        for (int i = 0; i < gap; i++)
        {
            //加上每一趟的步长 交换排序
            for (int j = i + gap; j < n; j+=gap)
            {
                //如果当前元素小于前驱元素 就交换
                if (a[j] < a[j - gap])
                {
                    int temp = a[j];
                    //将k初始化为j的前一个元素(与j相差gap个长度)
                    k = j - gap;
                    //记录后移查找插入的位置
                    while (k >= 0 && a[k] > temp)
                    {
                        a[k + gap] = a[k];//将a[j]前面的且大于temp的值的元素向后移动
                        k-=gap;
                    }
                    a[k + gap] = temp;
                }
            }
        }
    }
}

int main()
{
    int arr[] = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
    int length = sizeof(arr) / sizeof(arr[0]);
    shellSort(arr, length);
    for(int i = 0; i < length; i++)
    {
        printf("%d", arr[i]);
    }
    system("pause");
    return 0;
}

operation result 

 

Guess you like

Origin blog.csdn.net/ZER00000001/article/details/125617367