Classical sorting algorithm introduction and source code (c++ implementation)

 

Algorithm classification

Ten common sorting algorithms can be divided into two categories:

  • Comparative sorting : The relative order of elements is determined by comparison. Because its time complexity cannot exceed O(nlogn), it is also called nonlinear time comparison sorting.
  • Non-comparative sorting : The relative order between elements is not determined by comparison. It can break through the lower bound of time based on comparative sorting and run in linear time, so it is also called linear-time non-comparative sorting.

Algorithm complexity

Related concepts

  • Stable : If a is originally in front of b, and a=b, a is still in front of b after sorting.
  • Unstable : If a is originally in front of b, and a=b, a may appear behind b after sorting.
  • Time complexity : the total number of operations on sorted data. Reflects the law of the number of operations when n changes.
  • Space complexity: refers to the algorithm in the computer

A measure of the storage space required for internal execution, which is also a function of the data size n.

1. Bubble Sort (Bubble Sort)

Bubble sort is a simple sorting algorithm. It has repeatedly visited the sequence to be sorted, comparing two elements at a time, and swapping them if they are in the wrong order. The work of visiting the sequence is repeated until no more exchanges are needed, which means that the sequence has been sorted. The origin of the name of this algorithm is because the smaller the element will slowly "float" to the top of the sequence through exchange.

1.1 Algorithm description

  • Compare adjacent elements. If the first one is larger than the second, swap the two;
  • Do the same work for each pair of adjacent elements, from the first pair at the beginning to the last pair at the end, so that the last element should be the largest number;
  • Repeat the above steps for all elements except the last one;
  • Repeat steps 1~3 until the sorting is completed.

1.2 Animation demo

 1.3 code implementation

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

const int maxn = 100;
int arr[maxn], length;

//设置随机数组
void setRandArray(int a[]) {
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++) {
		int j = rand() % 100;
		a[i] = j;
	}
}

//输出数组
void showArray(int* a) {
	cout << "数组元素内容:";
	for (int i = 0; i < length; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

//冒泡排序
void bubbleSort(int *arr) {
	for (int i = 0; i < length - 1; i++) {
		for (int j = 0; j < length - 1 - i; j++) {
			if (arr[j] > arr[j + 1]) {
				int temp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
}

int main()
{
	cout << "输入元素个数:";
	cin >> length;
	setRandArray(arr);
	showArray(arr);
	bubbleSort(arr);
	cout << "冒泡排序后的数组:" << endl;
	showArray(arr);
	return 0;
}

2. Selection Sort (Selection Sort)

Selection-sort (Selection-sort) is a simple and intuitive sorting algorithm. Its working principle: first find the smallest (large) element in the unsorted sequence, store it at the beginning of the sorted sequence, and then continue to find the smallest (large) element from the remaining unsorted elements, and then put it in the sorted sequence At the end. And so on, until all elements are sorted.

2.1 Algorithm description

The direct selection and sorting of n records can be directly selected and sorted through n-1 times to obtain an ordered result. The specific algorithm is described as follows:

  • Initial state: the disordered area is R[1..n], and the ordered area is empty;
  • At the beginning of the i-th sorting (i=1,2,3...n-1), the current ordered area and disordered area are R[1..i-1] and R(i..n) respectively. This sorting trip selects the record R[k] with the smallest key from the current disordered area, and exchanges it with the first record R of the disordered area to make R[1..i] and R[i+1 ..n) Become a new ordered area with the number of records increased by one and a new disordered area with the number of records decreased by one;
  • At the end of n-1 pass, the array is ordered.

2.2 Moving picture demonstration

2.3 Code implementation

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

const int maxn = 100;
int arr[maxn], length;

//设置随机数组
void setRandArray(int a[]) {
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++) {
		int j = rand() % 100;
		a[i] = j;
	}
}

//输出数组
void showArray(int* a) {
	cout << "数组元素内容:";
	for (int i = 0; i < length; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

//选择排序
void selectionSort(int arr[]) {
	int minIndex, temp;
	for (int i = 0; i < length - 1; i++) {
		minIndex = i;
		for (int j = i + 1; j < length; j++) {
			if (arr[j] < arr[minIndex]) {
				minIndex = j;
			}
		}
		temp = arr[i];
		arr[i] = arr[minIndex];
		arr[minIndex] = temp;
	}
}

int main()
{
	cout << "输入元素个数:";
	cin >> length;
	setRandArray(arr);
	showArray(arr);
	selectionSort(arr);
	showArray(arr);
	return 0;
}

 

3. Insertion Sort (Insertion Sort)

The algorithm description of Insertion-Sort is a simple and intuitive sorting algorithm. Its working principle is to construct an ordered sequence. For unsorted data, scan from back to front in the sorted sequence, find the corresponding position and insert.

3.1 Algorithm description

Generally speaking, insertion sort is implemented on the array using in-place. The specific algorithm is described as follows:

  • Starting from the first element, the element can be considered to have been sorted;
  • Take out the next element and scan from back to front in the sorted sequence of elements;
  • If the element (sorted) is larger than the new element, move the element to the next position;
  • Repeat step 3 until you find the position where the sorted element is less than or equal to the new element;
  • After inserting the new element into this position;
  • Repeat steps 2~5.

3.2 Motion Picture Demonstration

3.2 Code implementation

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

const int maxn = 100;

//设置随机数组
void setRandArray(int a[], int length) {
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++) {
		int j = rand() % 100;
		a[i] = j;
	}
}

//输出数组
void showArray(int* a, int length) {
	cout << "数组元素内容:";
	for (int i = 0; i < length; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

//插入排序
void insertionSort(int *arr,int len){
	int preIndex,current;
	for(int i = 1; i < len; i++){
		preIndex = i - 1;
		current = arr[i];
		while(preIndex >= 0 && arr[preIndex] > current){
			arr[preIndex + 1] = arr[preIndex];
			preIndex--;
		}
		arr[preIndex + 1] = current;
	}
} 

int main()
{
	int arr[maxn], length;
	cout << "数组元素个数:";
	cin >> length;
	setRandArray(arr,length);
	showArray(arr,length);
	insertionSort(arr,length);
	showArray(arr,length);
	return 0;
}

4. Hill sorting (Shell Sort)

Shell invented in 1959, the first sorting algorithm to break O(n2), which is an improved version of simple insertion sort. The difference between it and insertion sort is that it will compare the farther elements first. Hill sorting is also called reduced incremental sorting .

4.1 Algorithm description

First divide the entire sequence of records to be sorted into several sub-sequences for direct insertion sorting, the specific algorithm description:

  • Choose an incremental sequence t1, t2,..., tk, where ti>tj, tk=1;
  • Sort the sequence k times according to the number of increment sequences k;
  • In each sorting pass, according to the corresponding increment ti, the sequence to be sorted is divided into several sub-sequences of length m, and each sub-table is directly inserted and sorted. Only when the increment factor is 1, the entire sequence is treated as a table, and the length of the table is the length of the entire sequence.

First, it divides the larger data set into several groups (logically grouped), and then inserts and sorts each group separately. At this time, the amount of data used by the insertion sort is relatively small (each group), and the efficiency of insertion Relatively high

Graphical Algorithm --- Hill Sort

Graphical Algorithm --- Hill Sort

It can be seen that he is a group whose subscripts are separated by 4 points, which means that the subscripts differ by 4 into a group. For example, in this example, a[0] and a[4] are a group, a[ 1] and a[5] are a group..., here the difference (distance) is called the increment

Graphical Algorithm --- Hill Sort

After insert sorting of each group, each group becomes ordered (the whole is not necessarily ordered)

Graphical Algorithm --- Hill Sort

At this point, the entire array becomes partly ordered (the degree of order may not be very high)

Graphical Algorithm --- Hill Sort

Then reduce the increment to half of the previous increment: 2, continue to divide the grouping. At this time, the number of elements in each grouping is more, but the part of the array becomes orderly, and the insertion sort efficiency is also higher.

Graphical Algorithm --- Hill Sort

In the same way, each group is sorted (insertion sort), so that each group is individually ordered

Graphical Algorithm --- Hill Sort

Finally, set the increment to half of the previous increment: 1, then the entire array is divided into a group. At this time, the entire array is close to order, and insertion sort efficiency is high

Graphical Algorithm --- Hill Sort

In the same way, sort the only set of data, and the sorting is complete

4.2 Animation demo

[video-to-gif output image]

4.3 Code implementation

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

const int maxn = 100;

//设置随机数组
void setRandArray(int a[], int length) {
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++) {
		int j = rand() % 100;
		a[i] = j;
	}
}

//输出数组
void showArray(int* a, int length) {
	cout << "数组元素内容:";
	for (int i = 0; i < length; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

void insertI(int arr[], int gap, int i){
	int inserted = arr[i];
	int j;
	//插入的时候按组进行插入(组内元素两两相隔gap)
	for(j = i - gap; j >= 0 && inserted < arr[j]; j -= gap){
		arr[j + gap] = arr[j];
	} 
	arr[j + gap] = inserted;
}

void shellSort(int arr[], int len){
	//进行分组,最开始时的增量(gap)为数组长度的一半
	for(int gap = len / 2; gap > 0; gap /= 2){
		//对各个分组进行插入排序
		for(int i = gap; i < len; i++){
			//将arr[i]插入到所在分组的正确位置上
			insertI(arr,gap,i);
		} 
	} 
}

int main()
{
	int arr[maxn], length;
	cout << "数组元素个数:";
	cin >> length;
	setRandArray(arr,length);
	showArray(arr,length);
	shellSort(arr,length);
	showArray(arr,length);
	return 0;
}

function shellSort(arr) {
    var len = arr.length;
    for (var gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
        // 注意:这里和动图演示的不一样,动图是分组执行,实际操作是多个分组交替执行
        for (var i = gap; i < len; i++) {
            var j = i;
            var current = arr[i];
            while (j - gap >= 0 && current < arr[j - gap]) {
                 arr[j] = arr[j - gap];
                 j = j - gap;
            }
            arr[j] = current;
        }
    }
    return arr;
}

5. Merge Sort (Merge Sort)

Merge sorting is an effective sorting algorithm based on merge operations. This algorithm is a very typical application of Divide and Conquer. Combine existing ordered subsequences to obtain a completely ordered sequence; that is, first make each subsequence in order, and then make the subsequences in order. If two ordered lists are merged into one ordered list, it is called 2-way merge.

The main idea of ​​merge sort is divide and conquer . The main process is:

  1. Cut n elements from the middle and divide them into two parts. (There may be 1 more number on the left than on the right)
  2. Divide step 1 into two parts, and then perform recursive decomposition. Until the number of elements in all parts is 1.
  3. Starting from the bottom layer, gradually merge the two sequenced numbers.

Consider a problem, how to merge two sequence of ordinal numbers into one sequence of ordinal numbers?

It's very simple. Since the two series are already in order, we only need to take the smallest number from the low order of the two series to PK. The loser is a small value, put this value into the temporary series, and The losing party continues to come up with a value to PK, until one party has no elements, and all the elements of the other party are followed by the temporary sequence. At this time, the temporary sequence is an orderly combination of two sequences. Merge in merge sort is to use this idea.

5.1 Algorithm description

  • Divide the input sequence of length n into two subsequences of length n/2;
  • Merge and sort these two subsequences respectively;
  • The two sorted subsequences are merged into a final sorted sequence.

5.2 Motion Picture Demonstration

 Write picture description here

Write picture description here

Write picture description here

Write picture description here

 Write picture description here

5.3 Code implementation

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

const int maxn = 100;

//随机数组
int arr[maxn];
int length;

//设置随机数组
void setRandArray(int a[]) {
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++) {
		int j = rand() % 100;
		a[i] = j;
	}
}

//输出数组
void showArray(int *a) {
	cout << "数组元素内容:";
	for (int i = 0; i < length; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

//将数组a的[L1,R1]与[L2,R2]区间合并为有序区间,此处,L2即为L1 + 1
void merge(int a[], int L1, int R1, int L2, int R2) {
	int i = L1; //i指向a[L1]
	int j = L2; //j指向a[L2]
	int temp[maxn]; //存放合并后的数组
	int index = 0; //index为temp的下标
	while (i <= R1 && j <= R2) {
		if (a[i] <= a[j]) {
			temp[index++] = a[i++];
		}
		else {
			temp[index++] = a[j++];
		}
	}
	while (i <= R1)
		temp[index++] = a[i++];
	while (j <= R2)
		temp[index++] = a[j++];
	//合并后,再赋回数组a
	for (int i = 0; i < index; i++) {
		a[L1 + i] = temp[i];
	}
}

void mergeSort(int arr[], int left, int right) {
	if (left < right) {  //只要left小于right
		int mid = (left + right) / 2;  //取left和right中点
		mergeSort(arr, left, mid);  //递归,左区间归并
		mergeSort(arr, mid + 1, right);	 //递归,右区间归并
		merge(arr, left, mid, mid + 1, right);  //左右区间合并
	}
}

int main() {
	cout << "输入数组元素个数:";
	cin >> length;
	setRandArray(arr);
	showArray(arr);
	mergeSort(arr, 0, length - 1);
	cout << "归并排序后:" << endl;
	showArray(arr);
	return 0;
}

5.4 Algorithm analysis

Merge sort is a stable sorting method. Like selection sort, the performance of merge sort is not affected by the input data, but it performs much better than selection sort because it is always O(nlogn) time complexity. The price is the need for additional memory space.

6. Quick Sort (Quick Sort)

 

7. Heap Sort (Heap Sort)

 

8. Counting Sort

 

9. Bucket Sort (Bucket Sort)

 

10. Radix Sort (Radix Sort)

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_43629083/article/details/109027542