Learning of sorting algorithm

Eight sorts

1, Internal sorting

1.1 insert sort

1.1.1 direct insertion sort

The core idea of direct insertion sorting is to compare all elements in the array with the previously arranged elements. If the selected elements are smaller than the sorted elements, they are exchanged until all elements are compared.
Therefore, from the above description, we can find that direct insertion sorting can be completed in two cycles:

  1. Layer 1 loop: traverse all array elements to be compared
  2. The second layer of loop: compare the selected elements in this round with the ordered elements.
    If: selected > ordered, the two are exchanged

Assuming that the sorting order is from left to right, the specific steps are as follows:

  1. The first element of the list is compared with the previous element. If it is smaller than the previous element (it does not exist), the position is exchanged. (in fact, this step can not be)

  2. The second element of the list is compared with the previous element (the first element). If it is smaller than the previous element, the position is exchanged.

  3. The third element of the list is compared with the previous element (the second element). If it is smaller than the previous element, the position is exchanged. If you have exchanged the position with the previous element and are now in the second position, then continue to compare with the previous element (the first element). If it is smaller than the previous element, then exchange the position again, and then repeat the comparison process again

... continue the above process until the last element completes the comparison

During the comparison movement, if the element does not need to be moved, it means that the element is sorted.
#include <stdio.h>
#Include < string. H > / / you can use the strlen() function

char a[10] = { 8,4,15,2,5,10,14,6,8,18 };

int main(void)
{
	int temp = 0;
	int len = strlen(a);  //Get array length
	
	for (int i = 1; i < len; i++)   //Traverse all array elements to be compared
	{
//Compare the current round of elements with the elements that have been arranged in order. If the previous elements are larger than the following elements, they will be exchanged all the time, otherwise the for loop will be ended
		for (int j = i-1; j >= 0 && a[j] > a[j + 1]; j--) 
		{
			temp = a[j];
			a[j] = a[j + 1];
			a[j + 1] = temp;
		}
	}
	
	for (int i = 0; i < 10; i++) //Print array
	{
		printf("%d ", a[i]);
	}
	getchar();//After execution, you do not return to the code window immediately, but wait for carriage return to view the operation results.
	return 0;
}

1.1.2 Hill sorting

Hill's sorting algorithm idea: group the arrays to be sorted according to the step gap, and then sort the elements of each group by direct insertion sorting method; Reduce the gap by half each time and cycle the above operation; When gap=1, the sorting is completed by direct insertion.
Similarly: from the above description, we can find that the overall implementation of hill sorting should be completed by three cycles:

  1. Layer 1 loop: divide gap in half and group the sequences until gap=1
  2. Second and third level loops: that is, the two loops required for direct insertion sorting. See above for detailed description.
#include <stdio.h>
#Include < string. H > / / you can use the strlen() function

char a[10] = { 8,4,15,2,5,10,14,6,8,18 };

int main(void)
{
	int len = strlen(a);  //Get array length
	int increment = len;
	int temp = 0;
	int j=0;
	while (increment > 1)
	{
		increment = increment / 3 + 1; //One of the incremental methods: divide by three and round down + 1
		for (int i = increment; i < len; i++)   //(len - increment) wheel
		{
			if (a[i- increment] > a[i])  //Compare the preceding number with the following number
			{
				temp = a[i];  //If the previous number is large, store the following number in temp
				j = i - increment;  //j stands for the previous number
				while (j >= 0 && a[j] > temp)
				{
					//If the preceding number is larger than the following number, the following number is equal to the preceding number
					a[j + increment] = a[j];  
					//If a[1] and a[5] are completely compared, a[5] is compared with a[9]. If a[5] > a[9], a[1] is compared with a[9]
					j = j - increment;  
				}
	//If a[1] > a[9], a[5] remains unchanged and a[1] and a[9] are interchangeable; If a[1] < a[9] & & a[5] > a[9], a[5] and a[9] are interchanged
				a[j + increment] = temp; 
			}
		}
	}

	for (int i = 0; i < 10; i++) //Print array
	{
		printf("%d ", a[i]);
	}
	getchar();//After execution, you do not return to the code window immediately, but wait for carriage return to view the operation results.
	return 0;
}

1.2 select sort

1.2.1 simple selection sorting

The basic idea of simple selection sorting: comparison + exchange

  1. Find the element with the smallest keyword from the sequence to be sorted;
  2. If the smallest element is not the first element of the sequence to be sorted, exchange it with the first element;
  3. From the remaining N - 1 elements, find the element with the smallest keyword and repeat steps (1) and (2) until the sorting is completed.
    Therefore, we can find that simple selection sorting is also realized through two-layer loops.
    The first layer of loop: traverse each element in the sequence in turn
    Layer 2 loop: compare the current element obtained by traversal with the remaining elements in turn. If it meets the condition of minimum element, it will be exchanged.
#include <stdio.h>
#Include < string. H > / / you can use the strlen() function

char a[10] = { 8,4,15,2,5,10,14,6,8,18 };

int main(void)
{
	int dat = 0;  //Array subscript used to hold the minimum value of each traversal
	int temp = 0;
	int len = strlen(a);  //Get array length
	for (int i = 0; i < len-1; i++) //Traverse the entire array (the last one is not used)
	{
		dat = i;
		for (int j = i + 1;j < len; j++)  //Traverse the array after i and compare with i
		{
			if (a[j] < a[dat])  //Find the smallest value and index the array of this value to dat
			{
				dat = j;
			}
		}
		temp = a[i];  //The value of dat is swapped with the position of the value of i, which is placed after the sorted list
		a[i] = a[dat];
		a[dat] = temp;
	}

	for (int i = 0; i < 10; i++) //Print array
	{
		printf("%d ", a[i]);
	}
	getchar();//After execution, you do not return to the code window immediately, but wait for carriage return to view the operation results.
	return 0;
}

1.2.2 heap sorting

Implementation of heap sorting:

  • Heap sort is a selective sort that uses the nature of the heap.

The basic idea is (large top reactor):

  1. Suppose the length of an initial to be sorted is n;

  2. The initial keyword sequence to be sorted (R0,R1,R2,..., Rn-1) is constructed into a large top heap, which is the initial disordered area;

  3. Exchange the top element R[0] with the last element R[n-1], and a new disordered region (R0,R2,..., Rn-2) and a new ordered region (Rn-1) are obtained, and R[1,2,..., n-2] < = R[n-1];

  4. Since the new heap top R[0] may violate the nature of the heap after exchange, it is necessary to adjust the current unordered area (R0,R1,..., Rn-2) to a new heap, and then exchange R[0] with the last element of the unordered area again to obtain a new unordered area (R0,R1,R2,..., Rn-3) and a new ordered area (Rn-2,Rn-1).

  5. Repeat this process until the number of elements in the ordered area is n-2, and the whole sorting process is completed.

#include <stdio.h>
#Include < string. H > / / you can use the strlen() function
//#include <stdlib.h>


void HeapAdjust(char array[], int i, int len) 
{
    int MaxChild;  //Used to store the largest child node
    int Parent;  //Used to store the value of the parent node
    int LeftChild  = 2 * i + 1;  //Assuming that the parent node is i, its left child node is 2i+1
    int RightChild = 2 * i + 1;  //Assuming that the parent node is i, the right child node is 2i + 2

    for (Parent = array[i]; 2 * i + 1 < len; i = MaxChild)  //Each time, the maximum child node is judged downward as the parent node
    {
        
        LeftChild = 2 * i + 1;  
        RightChild = 2 * i + 2; 
        MaxChild = LeftChild;  //Let's assume that the left node is the maximum
        if (MaxChild != len- 1 && array[RightChild] > array[LeftChild])  //First judge whether the node exceeds the super degree, then judge which of the left and right child nodes is large, and find the child node with the largest value
        {
                MaxChild = RightChild;  //If the right node is large, come in and change MaxChild into the right child node
        }
    
        if (Parent < array[MaxChild])  // If the larger child node is larger than the parent node, move the larger child node up to replace its parent node
        {
            array[i] = array[MaxChild];
        }
        else  // Otherwise exit the loop
        {
            break;
        }
    }
    array[i] = Parent;  // Finally, put the original parent node in the appropriate position

}


void HeapSort(char array[], int length)
{
    //The process of building a heap    
    for (int i = (length / 2 - 1); i >= 0; i--)  // After adjusting the first half elements of the sequence (i.e. each node with children), there is a large top heap. The first element is the largest element of the sequence, which is judged from bottom to top
    {
        HeapAdjust(array, i, length);
    }


    for (int i = length - 1; i > 0; i--)  //By constantly filtering the maximum value, while constantly filtering the remaining elements
    {
        int temp;
    
        temp = array[i];      // Exchange the first element with the current last element to ensure that the current last element is the largest in the current sequence
        array[i] = array[0];
        array[0] = temp;   //array[i] is the maximum, arrat[i-1] is the second largest, arrat[i-2] is the third largest, and so on


        HeapAdjust(array, 0, i);   // Continuously narrow the range of adjusting heap, and ensure that the first element is the maximum value of the current sequence after each adjustment
    }

}

int main()
{
    int len;
    char arr_test[17] = {15, 8, 12, 4, 2, 3, 5, 1, 6, 9, 0, 7, 10, 11, 14, 15, 1 };  //test data

    len = sizeof(arr_test);  //Calculate array length
    HeapSort(arr_test, len);  //Heap sorting algorithm


    for (int i = 0; i < len; i++)  //Print the sorted data
    {
        printf("%d  ", arr_test[i]);
    }   
    getchar();  //After execution, you do not return to the code window immediately, but wait for carriage return to view the operation results.
    return 0;

}

1.3 exchange sorting

1.3.1 bubble sorting

Bubble sorting is one of the basic sorting algorithms. Its idea is to compare adjacent elements in pairs. The larger number sinks and the smaller number rises. In this way, the maximum (small) value will be arranged at one end after a comparison. The whole process is like bubbles, so it is called bubble sorting.

Bubble sorting is simple:

  1. Compare the left and right elements in the sequence in order to ensure that the element on the right is always greater than the element on the left; (after the first round, the last element of the sequence must be the maximum value of the current sequence)
  2. Perform step 1 again for the remaining n-1 elements in the sequence;
  3. For the sequence with length N, a total of n-1 rounds of comparison need to be performed; (using the while loop can reduce the number of executions)
#include <stdio.h>
#Include < string. H > / / you can use the strlen() function

int main()
{
    char a[10] = { 12 ,43,9,13,67,98,101,89,3,35 };//Unordered sequence of ten numbers
    int temp,len;
    len = sizeof(a);
    
    //Bubble sorting
    for (int i = 0; i < len-1 ; i++)//The number sequence of N numbers is scanned n-1 times in total. Each time, the maximum number is arranged in the back, and then the ones not arranged in the front are photographed
    {
        for (int j = 0; j < len - i -1; j++)//Each scan ends when a[n-i-2] is compared with a[n-i-1]
        {
            if (a[j] > a[j + 1])//If the last digit is smaller than the previous digit, exchange the positions of the two numbers (in ascending order)
            {
                temp = a[j + 1];
                a[j + 1] = a[j];
                a[j] = temp;
            }
        }
    }
     
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", a[i]);
    }
    getchar();  //After execution, you do not return to the code window immediately, but wait for carriage return to view the operation results.
    return 0;
}

1.3.1 quick sort

Basic idea of quick sorting: digging and filling + divide and conquer

  1. First, take a number from the sequence as the reference number; (here, select the first number in the sequence as the benchmark number)
  2. In the partition process, all numbers larger than this number are placed on its right, and all numbers less than or equal to it are placed on its left;
  3. Then repeat the first and second steps for the left and right intervals until there is only one number in each interval;

The pseudo code is described as follows:

  1. i =L; j = R; Dig out the reference number to form the first pit a[i].
  2. j – find the number smaller than it from back to front, dig out the number and fill it in the previous pit a[i].
  3. i + + find a number larger than it from front to back. After finding it, dig out the number and fill it into the previous pit a[j]
  4. Repeat steps 2 and 3 until i==j, and fill the benchmark number in a[i]
  5. Then sort the numbers on the left of K and the numbers on the right of K in the same way as above
#include <stdio.h>
#Include < string. H > / / you can use the strlen() function


void QuickSort(char* arr, int low, int high)
{
    if (low < high)
    {
        int i = low;
        int j = high;
        int k = arr[low];
        while (i < j)
        {
            while (i < j && arr[j] >= k)     // Find the first number less than k from right to left
            {
                j--;  //If you can't find it, keep looking one space ahead
            }

            if (i < j)  //Put the found number less than K in front, the first number less than K in the first, the second number less than K in the second, and so on
            {
                arr[i] = arr[j];  //Put the smallest number found in a[i]
                i++;  //i move back one space
            }
    
            while (i < j && arr[i] < k)      // Find the first number greater than or equal to k from left to right
            {
                i++;  //If you can't find it, keep looking in the next space
            }
    
            if (i < j)  //Put the found number greater than K in the back, the first number greater than K in the last, the second number greater than K in the penultimate, and so on
            {
                arr[j] = arr[i];  //Put the maximum number found in a[j]
                j--;  //j move back one space
            }
        }
        //So far, all values less than k are to the left of K; Values greater than k are to the right of K
    
        arr[i] = k; //Put the reference value into the remaining pit
    
        // Recursive call
        QuickSort(arr, low, i - 1);     // Number to the left of sort k
        QuickSort(arr, i + 1, high);    // Number to the right of sort k
    }

}
// Main function
int main()
{
    int len;
    char array[10] = { 12,85,25,16,34,23,49,95,17,61 };
    len = sizeof(array);
    

    QuickSort(array, 0, len - 1);  // Quick sort
    for (int i = 0; i < len; i++)  //Print out
    {
        printf("%d ", array[i]);
    }
    getchar();  //After execution, you do not return to the code window immediately, but wait for carriage return to view the operation results.
    return 0;
}

1.4 merge sort

  1. Merge sort is an effective sort algorithm based on merge operation. This algorithm is a typical application of divide and conquer method. Its basic operations are: merging the existing subsequences to achieve a completely ordered sequence; That is, each subsequence is ordered first, and then the subsequence segments are ordered. If two ordered tables are merged into one, it is called two-way merging, which uses the algorithm of sacrificing space for time
  2. Merging and sorting actually involves two things:
  • Split: split the sequence in half each time;
  • Merge: sort and merge the divided sequence segments in pairs;

Therefore, merge sort is actually two operations, split + merge

Split:

Consolidation:

  1. How to decompose?
    Here, I use the recursive method. First, I divide the sequence to be arranged into two groups A and B; Then repeat the grouping of a and b sequences; Until there is only one element in the group after grouping, we think that all elements in the group are in order, and the grouping ends;
  2. How to merge?
    arr[first,..., mid] is the first segment, arr[mid+1,..., last] is the second segment, and both ends have been ordered. Now we want to synthesize both ends to temp[first... Last] and also orderly:
  • Firstly, take out the elements from the first paragraph and the second paragraph in turn, and assign the smaller elements to temp [];
  • Repeat the previous step. When the assignment of one section ends, assign the remaining elements of another section to temp [];
  • At this time, copy the elements in temp [] to arr [], and the resulting arr[first... last] is ordered;

  1. Code parsing
#include<stdio.h>
#include<string.h>

#define ArrLen 20

void merge(char arr[], int start, int mid, int end)  //Sort intervals
{
	int result[ArrLen];  //Used to merge two intervals
	int temp = 0;  //Used to store ordered sequences after merging
	int i = start;  //The beginning of the first interval
	int j = mid + 1;  //The beginning of the second interval
	while (i <= mid && j <= end)  //Divide the interval into [start,mid] and [mid+1,end] for sorting
	{
		if (arr[i] < arr[j])  //Compare the first element of the two intervals. If the first element of interval 1 is small, put it in the first place of the result, and then compare the second element of interval 1 with the first element of interval 2. Whoever is small will put it in the next place of the result, and so on until one of the intervals is traversed
		{
			result[temp++] = arr[i++];
		}
		else  //If the element of interval 2 is small, put it into result, and so on
		{
			result[temp++] = arr[j++];
		}
	}

	if (i == mid + 1)  //If the first area has been traversed
	{
		while (j <= end)  //And the second area has not been traversed
		result[temp++] = arr[j++];  //Rank the values of the second interval after the result in order
	}
	if (j == end + 1)  //If the second area has been traversed
	{
		while (i <= mid)  //And the first area has not been traversed
		result[temp++] = arr[i++];  //Rank the values of the first interval after the result in order
	}
	for (j = 0, i = start; j < temp; i++, j++)  //Put the sorted array result [] into the arr [] array
	{
		arr[i] = result[j];
	}
}

void mergeSort(char arr[], int start, int end)
{
	if (start >= end)  //If there is only one value left in the interval, stop recursion and return 0
	{
		return;
	}
	int mid = (start + end) / 2;   //Take intermediate value
	mergeSort(arr, start, mid);    //Divide the de interval into [start,min] and [min+1,end] with an intermediate value
	mergeSort(arr, mid + 1, end);  //Divide the de interval into [start,min] and [min+1,end] with an intermediate value
	merge(arr, start, mid, end);   //Sort the separated intervals each time
}

int main()
{
	int len;
	char arr[] = { 4, 7, 6, 5, 2, 1, 8, 2, 9, 1 };
	len = sizeof(arr);

	mergeSort(arr, 0, len-1);

	for (int i = 0; i < 10; i++)  //Print out
	{
		printf("%d ", arr[i]);
	}

	getchar();  //Do not return to the code window immediately after execution. Wait for the carriage return before returning to view the operation results
//	system("pause");
	return 0;
}

1.5 cardinality sorting

Cardinality sorting (taking shaping as an example),

  • Split the integer hexadecimal by each bit, and then compare each bit from low to high. Sort after each comparison until the entire array is in order
    It is mainly divided into two processes:
  1. Allocation: start with individual bits and put them into buckets 0 ~ 9 according to the bit value (0-9) (for example, 53, if the bit is 3, put them into bucket 3; 187, if the bit is 7, put them into bucket 7)
  2. Collection: then put the data placed in buckets 0 ~ 9 into the array in order
  3. Repeat the process of (1) and (2) from single bit to the highest bit until the order is arranged (for example, the maximum number of 32-bit unsigned integer is 4294967296, and the maximum bit is 10 bits)

For example:

  • Suppose there is a data sequence to be arranged: 73 22 93 43 55 14 28 65 39 81

  • First, according to the value of the single digit, when traversing the data, they are respectively assigned to the buckets numbered 0 to 9 (the single digit value corresponds to the bucket number one by one).

The allocation result (logical imagination) is shown in the figure below:

  • After the distribution, the data contained in all buckets will be collected and concatenated according to the bucket number from small to large (from top to bottom in the bucket)

  • The following still disordered data sequence is obtained: 81 22 73 93 43 14 55 65 28 39

  • Then, another allocation is made, this time according to the ten digit value (the principle is the same as above), and the allocation result (logical imagination) is shown in the following figure:

  • After the distribution, the data contained in all barrels (the principle is the same as above) will be collected and connected in series

  • The following data sequence is obtained: 14 22 28 39 43 55 65 73 81 93

  • It can be seen from the observation that the original unordered data sequence has been sorted at this time

  • If the sorted data sequence has more than three digits, repeat the above actions until the highest digit

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

#define Len 10 / / number of arrays
#define RADIX_ 10 / / shaping sorting, there are 10 buckets, corresponding to 0-9 respectively
#define KeyNum 10 / / the number of keywords. This is the number of integer digits. You can filter up to 10 digits (digits, tens, hundreds, thousands...)


// Find the pos data of num from low to high
int GetNumInPos(int num, int pos)
{
	int temp = 1;
	for (int i = 0; i < pos - 1; i++)//Filter out one or ten or hundreds of bits in num array
	{
		temp *= 10;
	}
	return (num / temp) % 10;  //Go back to the one you found
}


void RadixSort(int* arr, int arr_Len)
{
	int* temp[RADIX_10];    //The sequence space of 0 ~ 9 is generally 10 barrels
	int dat;  //It is used to store the number stored in temp[num]
	int num;  //Used to store the value returned by the function GetNumInPos()

	for (int i = 0; i < 10; i++)  //Allocate space for temp
	{
		temp[i] = (int*)malloc(sizeof(int) * (arr_Len + 1));  //Allocate space for array temp
		temp[i][0] = 0;    //Each temp[i][0] is used to record how many data are put in this temp[i]
	}
	
	for (int pos = 1; pos <= KeyNum; pos++)    //Starting from bits, a total of 10 bits are cycled
	{
		for (int i = 0; i < arr_Len; i++)    //In the allocation process, each number in arr [] is allocated once
		{
			num = GetNumInPos(arr[i], pos);  //Get the pos bit in arr[i]
			temp[num][0]++;  //A number is added to temp[num], so the 0th bit of temp[num] is added with 1
			dat = temp[num][0];  //Tell dat how many numbers are saved in temp[num]
			temp[num][dat] = arr[i];  //Put the data into the dat bit of temp[num]
		}
	
		for (int i = 0, j = 0; i < 10; i++)    //collect
		{
			for (int k = 1; k <= temp[i][0]; k++)  //Return the allocated to the arr [] array in order
			{
				arr[j] = temp[i][k];  
				j++;
			}
			temp[i][0] = 0;    //And reset the bits used to record the number
		}
	}

}

int main()
{
	int arr_test[Len] = { 854, 424, 227, 38, 524, 124, 635, 922, 140, 75 };

	RadixSort(arr_test, Len);  //Cardinality sort
	
	for (int i = 0; i < Len; i++)  //Print out
	{ 
		printf("%d  ", arr_test[i]);
	}
	
	getchar();  //After execution, you do not return to the code window immediately, but wait for carriage return to view the operation results.
	return 0;
}

Dynamic allocation of playing memory needs to be released ~ otherwise you may lose your job

1.6 summary

Tags: Algorithm data structure

Posted on Fri, 17 Sep 2021 08:28:54 -0400 by splat78423