Data structure - C language implements common sorting (insertion sorting, Hill sorting, selection sorting, heap sorting, bubble sorting)

introduction:

It is now 13:19 on June 23, 2023, Beijing time, and I had a very happy Dragon Boat Festival. Since I just came home from school, the food intensity suddenly increased by two or three levels. This also caused my stomach to be overwhelmed, and I was going to go to the gym to burn off the surplus calories later. Going home to accompany grandpa through the final stage of life is the most important thing for me this summer vacation. Since my grandfather became seriously ill, my family needs to take care of me in my daily life. Maybe fifty or sixty years later, my descendants will be able to accompany me in the last stage of my life.
insert image description here

The concept of sorting

The so-called sorting is the operation of arranging a set of data in increasing or decreasing order according to the size of one or some of the keywords. Sorting is everywhere in daily life, for example, there will be sorting of grades in school exams, and there will be sorting of sales or prices when we shop.
Reasonably introduce the sorting stability. Assume that in the data to be sorted, there are multiple data with the same keyword. After sorting, the relative order of these records remains unchanged, that is, in the original sequence, r[i] = r[j], and r[i] is before r[j], and in the sorted sequence, r[i] is still before r[j], then the sorting algorithm is said to be stable; otherwise it is called for unstable.

insertion sort

Thought

The idea of ​​insertion sorting is actually similar to when we play poker, every time we draw a card, we will sort it. Here, in ascending order, each insertion sort compares the data to be sorted with the data in front of it. When the data to be sorted is smaller than the previous one, it is exchanged, and it is moved forward, and the data larger than it is backward. Move, stop single-pass sorting until the previous data is smaller than it or the subscript of the sorted data is less than 0.
insert image description here

Single pass sorting code implementation

According to the idea of ​​insertion sorting, we start inserting data at subscript 1 for sorting, so when the previous data is larger than the latter data, we will exchange. Stop single-pass sorting until the inserted position is less than the effective range of the array. In this way, the small numbers will move forward, and the large numbers will move backward as a whole.

        int end ;//用于表示当前数据的下标
        int tmp ;//插入数据的值
        while(end >= 0)
        {
    
    
        //前一个数比它小就覆盖
            if(tmp < arr[end])
            {
    
    
                arr[end+1] = arr[end];
                end--;
            }
         //否则就结束单趟排序
            else
            {
    
    
                break;
            }
        }

Complete code implementation

With the realization of single-pass sorting, we can write the outer loop according to the overall idea. That is, the outer loop starts at 1 and ends at n-1. When the single-pass sorting ends, the numbers that exceed the range of the array need to be rewritten back into the array. For example, when end == -1, it must be written at the subscript 0.

//插入排序——升序
void InsertSort(int* arr, int n)
{
    
    
    for(int i = 1; i < n;i++)
    {
    
    
        int end = i - 1 ;
        int tmp = arr[i];
        while(end >= 0)
        {
    
    
            if(tmp < arr[end])
            {
    
    
                arr[end+1] = arr[end];
                end--;
            }
            else
            {
    
    
                break;
            }
        }
        arr[end+1] = tmp;
    }
}

Feature Summary

1. When the data is closer to the ordered insertion sort, the efficiency of insertion sorting is higher. When sorting in ascending order, when the data is in ascending order (best case), the time complexity of insertion sorting is O(N). Because in the best case, you only need to traverse the data n-1 times and make a judgment.
2. In the worst case, the time complexity of insertion sorting is O(N^2). That is, when sorting in ascending order, when the data is in descending order. Because the time complexity of moving data in a single sorting is O(N), and the overall sorting needs to be N-1 times, the time complexity is O(N ^ 2).
3. The time complexity of insertion sorting is O(N^2), and the space complexity is O(1).
Fourth, insertion sort is a stable sort. The definition of sort stability is that the relative positions of the same elements in the array remain unchanged before and after sorting.

Hill sort

Thought

Hill sorting is also called shrinking incremental sorting. The idea is to take an integer grouping identifier. Here I use gap to represent this value, and divide the data to be sorted into multiple groups according to the gap of the gap step. And directly insert and sort the multiple sets of data to make them closer to order. At the beginning, the gap value is relatively large, and the large number will be moved back quickly, and the small number will be pushed forward. As the gap gradually becomes smaller, the data is getting closer and closer to order. Finally, when gap=1, the data is already close to order, and direct insertion sorting will be performed at this time.
insert image description here

insert image description here

Single pass sorting code implementation

The implementation idea of ​​single-pass sorting is the same as insertion sorting. The difference is that single-pass sorting needs to be grouped here, so it is grouped by group interval gap to perform single-pass sorting. When gap==1 in the last pass, it is insertion sorting.

	int end;
	int tmp;
	while(end >= 0)
	{
    
    
	    if(tmp < arr[end])
	    {
    
    
	        arr[end+gap] = arr[end];
	        end-= gap;
	    }
	    else
	    {
    
    
	        break;
	    }
	}

Code

There are many ways to take the gap here, and most of them use /2 or /3+1 to take the gap value. I'll take /2 as an example here. The logic of the control of the outer loop is generally to control the gap to make the interval locally ordered. Finally, when the gap==1, the insertion sort is directly performed on the nearly ordered array. The following code can be used as a reference. The specific writing method depends on personal preference, and the idea is basically the same.

//希尔排序——升序
void ShellSort(int* arr, int n)
{
    
    
    int gap = n;
    while(gap > 1)
    {
    
    
        gap/=2;
        for(int i = 0; i < n-gap;i++)
        {
    
    
            int end = i ;
            int tmp = arr[i+gap];
            while(end >= 0)
            {
    
    
                if(tmp < arr[end])
                {
    
    
                    arr[end+gap] = arr[end];
                    end-= gap;
                }
                else
                {
    
    
                    break;
                }
            }
            arr[end+gap] = tmp;
        }
    }
}

Feature Summary

1. Hill sort is actually an optimization of direct insertion sort. By pre-sorting according to gap grouping, the embarrassment of direct insertion sorting in the worst case is greatly optimized, and large numbers can be quickly moved back and small numbers can be moved forward.
2. When the gap is greater than 1, it is pre-sorted. The purpose is to make the array closer to order and optimize the number of direct insertion sorts. This is a great degree of optimization for the idea of ​​direct insertion sorting, with high efficiency.
3. Since there is no official unified value for the value of the gap, it must be guaranteed that the gap must be 1 for the last time. Therefore, there is no way to define a standard in terms of time complexity. Here I will quote the content of Teacher Yan to give a better explanation.
insert image description here
The time complexity of Hill sorting is O(N^1.3), so Hill sorting can also be included in the sorting of O(N LogN) time complexity. When N is getting bigger and bigger, there is still a big gap between N^1.3 power and N LogN
insert image description here
4. Hill sorting is an unstable sorting, because the pre-sorting order of gap groups may be affected.

selection sort

Thought

It is to traverse the entire array every time, find the maximum/minimum value of the entire array and put it in the appropriate position to complete the single-pass sorting. The maximum and minimum values ​​can be calculated according to each traversal of the array, and the selection sort can also be optimized to put the maximum and minimum values ​​in the appropriate position at one time. However, a special judgment is required to avoid the overlapping problem of left and max, which leads to the inability to make max reach the proper position after the exchange. Then repeat the above steps until there is only one data in the interval, then the sorting ends.
insert image description here

Single pass sorting code implementation

Traverse the array, find the maximum and minimum values ​​and move them to the corresponding subscript positions. It should be noted that since the large and small are searched at the same time, it is necessary to avoid overlapping special judgments, otherwise the data will be overwritten.

 //每一次找出区间内最大和最小的数
	int mini;
	int maxi;
	for(int i = left + 1; i <= right; i++)
	{
    
    
	    if(arr[mini] > arr[i])
	        mini = i;
	    if(arr[maxi] < arr[i])
	        maxi = i;
	}
	//由于同时找大和找小,所以要避免重叠特殊判断
	Swap(&arr[left],&arr[mini]);
	if(maxi == left)
	    maxi = mini;
	Swap(&arr[right],&arr[maxi]);

Code

The whole is to gradually shrink from the 0 to n-1 interval to the middle. When left >= right, it means that there is no valid interval.

//选择排序
void SelectSort(int* arr, int n)
{
    
    
    int left = 0;
    int right = n - 1;
    while(left < right)
    {
    
    
        //每一次找出区间内最大和最小的数
        int mini = left;
        int maxi = left;
        for(int i = left + 1; i <= right; i++)
        {
    
    
            if(arr[mini] > arr[i])
                mini = i;
            if(arr[maxi] < arr[i])
                maxi = i;
        }
        //避免重叠特殊判断
        Swap(&arr[left],&arr[mini]);
        if(maxi == left)
            maxi = mini;
        Swap(&arr[right],&arr[maxi]);
        
        left++;
        right--;
    }
}

Feature Summary

1. Selection sorting is easier to understand, but the efficiency is too low. Usually it is not used for sorting either.
2. Its time complexity is stable at O(N^2) as before, and its space complexity is O(1).
Three, it is an unstable sort. To give an example, if the maximum value is repeated, the maximum value that should have been at the front will be swapped to the end first, causing the order of the same value to be out of order.

heap sort

Click here to jump to the introduction of heap sorting . Since it has been introduced before, I won’t go into details here. According to the introduction of direct selection sorting introduced above, it is not difficult to find that heap sorting is actually an optimization of direct selection sorting. However, this is a kind of sorting by relying on the structure of a complete binary tree such as a heap to build a heap to improve the efficiency of selecting large or small roots.

Code

void AdjustDown(int* a, int n, int parent)
{
    
    
    int child = parent * 2 + 1;
    while (child < n)
    {
    
    
        // 选出左右孩子中大的那一个
        if (child + 1 < n && a[child + 1] > a[child])
        {
    
    
            ++child;
        }
		//判断父子关系
        if (a[child] > a[parent])
        {
    
    
            Swap(&a[child], &a[parent]);
            //迭代
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
    
    
            break;
        }
    }
}


//堆排序
void HeapSort(int* arr, int n)
{
    
    
    //向下调整建堆
    for (int i = (n - 1 - 1) / 2; i >= 0; --i)
    {
    
    
        AdjustDown(arr, n, i);
    }
    //排序:大数往下沉,然后堆顶向下调整堆
    int end = n - 1;
    while (end > 0)
    {
    
    
        Swap(&arr[end], &arr[0]);
        AdjustDown(arr, end, 0);

        --end;
    }
}

Feature Summary

1. Use the heap data structure to select trees, which greatly improves the efficiency.
2. The time complexity of heap sorting is O(N*LogN), and the space complexity is O(1).
3. Heap sort is an unstable sort.

Bubble Sort

Thought

The idea of ​​bubble sorting is to compare and exchange with the following data sequentially starting from the 0th position. Taking ascending order as an example, when the previous number is greater than the next number, the positions of the two numbers are exchanged until the end of the single trip, and finally the largest number will appear where it should appear. In the worst case, it takes n-1 bubble sorting.

Single pass sorting code implementation

Compare two by two until you find the largest value in a single trip, and let it go to its proper position.

  for (int i = 1; i < n; i++)
        {
    
    
            if (arr[i - 1] > arr[i])
            {
    
    
                Swap(&arr[i - 1], &arr[i]);
            }
        }

Code

//冒泡排序
void BubbleSort(int* arr, int n)
{
    
    
    for (int j = 0; j < n - 1; j++)
    {
    
    
        //若有序就跳出循环
        //优化后,最好情况时间复杂度为O(N)
        int flag = 0;
        for (int i = 1; i < n-j; i++)
        {
    
    
            if (arr[i - 1] > arr[i])
            {
    
    
                Swap(&arr[i - 1], &arr[i]);
                flag = 1;
            }
        }
        if (flag == 0)
        {
    
    
            break;
        }
    }
}

Feature Summary

1. Bubble sorting is a sorting algorithm with teaching significance.
2. The time complexity of bubble sorting is O(N^2), and the space complexity is O(1).
3. Bubble sort is a stable sort.

Guess you like

Origin blog.csdn.net/m0_71927622/article/details/131240589