Diagrams and detailed codes of several commonly used sorting algorithms that must be met when entering a large factory
The sorting algorithm is the most popular algorithm we have ever come into contact with. Because of this, many sorting algorithms have been born, such as the well-known bubble sorting, selection sorting, and insertion sorting. The principles of these are very simple. After understanding The code implementation is also relatively simple, so the author will not repeat the cliché here, and students who don’t know can search related blogs and video learning.
Next, this article mainly introduces five relatively complex sorting algorithms, namely quick sorting, Hill sorting, merge sorting, radix sorting and heap sorting. Some students may ask that there are already several sorting algorithms above. Why are there so many different algorithms born? In fact, you can know this problem after serious thinking. The simplest point is that the above algorithms cannot meet some of our needs to a certain extent. This is about a section of algorithm or code. The time complexity is higher. It can be simply understood as the number of executions of valid code in a piece of code. If you want to understand the clear meaning, you can find relevant information for learning.
Back to the topic, this article mainly introduces the diagrams and code implementation of these five sorting algorithms. This is the author who spent a whole day working hard to sort it out. The author is also a novice algorithm. You can exchange, discuss and share more. I hope the boss can point out the wrong place.
Article Directory
a quick sort
The idea of quick sorting is to complete the sorting by continuously transforming the axis point elements
What are Pivot Elements?
In ascending order, the axis point element is that all elements on the left are smaller than this element, and all elements on the right are larger than this element
Taking the following picture as an example, we first need to assume a pivot point element, then place all smaller ones on its left and larger ones on its right, and then complete the final sorting recursively
The process is as follows:
1) First of all, two pointers must be defined. At the beginning, they point to the beginning and the end respectively, which are left and right respectively.
2) Assuming that the first element is used as the pivot point element, we first scan from the right to the left, and compare the value of the right position with the assumed index value. ① If it is greater than the value of the pivot element, it will not move, and the right pointer points
to Move to the left once, repeat the above operation
②If it is smaller than the value of the pivot element, assign the value to the position corresponding to left, and move left to the right once, at this time it needs to be reversed, start scanning from left to right, repeat the above operation
3) Repeat the operation of the above 2 until the critical point, that is, left < right, exit the operation
4) Assign the value of the hypothetical axis point element to the position of the last index, and return the index
At this point, the first round of selecting the pivot element is completed, and we can know that the left side of the pivot element is smaller than the pivot element, we can select the pivot element again from the left to the pivot element, and use the pivot From the point element to the right, select the axis point element once as the boundary, and so on, we can easily sort all the elements. When recursing, we need to determine a clear boundary to ensure that the recursive function can backtrack, otherwise it will cause an infinite loop. , we can know that the limit at this time is left < right, and the function can be called until the limit is met within this limit, that is, there is only one element left, which ensures that the sorting of all elements is successful
code show as below:
public class QuickSort {
public static void main(String[] args) {
int[] arr = {
6,3,5,8,1,9,7,2,0};
int i = pivotIndex(arr, 0, arr.length);
System.out.println(Arrays.toString(arr));
}
//对[begin,end) 范围内的元素进行快速排序
public static void quickSort(int[] arr,int begin,int end){
if (end - begin < 2){
return;
}
//对范围内元素进行快速排序确定轴点
int mid = pivotIndex(arr, begin, end);
//对轴点元素左边进行快速排序
quickSort(arr, begin, mid);
//对轴点元素右边进行快速排序
quickSort(arr, mid + 1, end);
}
/**
* 构建范围在[begin,end)范围内元素的轴点元素
*
* @return 返回轴点元素的最终位置
*/
public static int pivotIndex(int[] arr,int begin,int end){
//备份begin元素值
int pivot = arr[begin];
//将end元素指向最后一个元素
end--;
//具体操作逻辑构建轴点元素位置
while (begin < end){
while(begin < end){
//从右往左判断
if (pivot < arr[end]){
end--;
}else {
arr[begin++] = arr[end];
break;
}
}
while(begin < end){
//从左往右判断
if (pivot > arr[begin]){
begin++;
}else {
arr[end--] = arr[begin];
break;
}
}
}
//将备份的轴点元素放入最终的位置
arr[begin] = pivot;
return begin;
}
}
Two Hill sort
Hill sorting is the optimization of direct insertion sorting, because considering the limit of insertion sorting, it may cause the worst time complexity
The principle is based on insertion sorting. First, the entire array is grouped by step (number of elements/2). The distance between elements in the same group is the step value, as shown in the figure below.
The elements in the same group are compared, and in ascending order, the smaller ones are placed in front and the larger ones are placed in the back
For the second time, step /= 2, and perform the above operations again until step = 1. At this time, it is the normal insertion sort, but we can see that after the above operations, the array is almost sorted
The biggest difference between Hill sorting and insertion sorting is to consider a grouping situation, and the other ideas are exactly the same as insertion sorting
code show as below:
The following two implementations are the same as direct insertion sort, exchange and shift
//希尔排序,就是进行分组之后的直接插入排序
public class ShellSort {
public static int count = 0;
public static void main(String[] args) {
int[] arr = {
6,3,5,8,1,9,7,2,0};
shellsort1(arr);
}
//希尔排序之交换式
public static void shellsort(int[] arr){
for (int step = arr.length/2; step > 0 ; step /= 2){
for (int i = step; i < arr.length ; i++) {
for (int j = i-step; j >= 0 ; j -= step) {
if (arr[j] > arr[j+step]){
int temp = arr[j];
arr[j] = arr[j+step];
arr[j+step] = temp;
}
}
}
System.out.println("希尔排序第"+ ++count +"轮:" + Arrays.toString(arr));
}
}
//希尔排序之移位式
public static void shellsort1(int[] arr){
//将数组分组,并进行判断移位
for (int step = arr.length/2; step > 0 ; step /= 2) {
//这个就和简单的插入排序基本相同,只是多了一个分组的步长,需要考虑每一轮分组的情况
for (int i = step; i < arr.length; i++) {
int j = i;
int temp = arr[j];
if (arr[j] < arr[j - step]){
while (j - step >= 0 && temp < arr[j - step]){
arr[j] = arr[j - step];
j -= step;
}
}
arr[j] = temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
triple merge sort
Merge sort is a sorting algorithm implemented by using the idea of divide and conquer
Divide: Use recursion to break down the array into the smallest unit, that is, each element
And: in the process of backtracking the recursive function, the decomposed elements are sorted, and the sorting is completed when the backtracking is completed
Specifically as shown in the figure below:
The next step is to implement the sorting process and diagram in the backtracking process
The sorting in the whole backtracking process has the following steps:
1) First, a temporary array is needed to store the sorted elements
2) Three pointers left, mid, and right are needed to locate the specific position of the element and perform operations
3) Start sorting ideas
①Because they are all sorted sequentially, they are all operated from left to right, compare the values at the index positions of left and tmp, and put the smaller ones in the temporary array. At this time, the index pointer moves to the right once, and the array index starts from 0
② Repeat the above operations until the critical condition is reached, that is, left <= mid && tmp <= right
③Put the remaining elements into the temporary array in turn, and the array is completely ordered at this time
④ At this time, copy the value of the temporary array to the corresponding index position of the original array in
turn (Note: it is very important, because it is a recursive backtracking process, each pointer corresponds to the beginning, end and middle position of the decomposed part, so The last sorted order needs to be used in this sorting, so the sorted temporary array should be copied to the corresponding index position of the original array, which will be reflected in the following code)
code show as below:
//归并排序
public class MergeSort {
public static void main(String[] args) {
int[] arr = {
6,3,5,8,1,9,7,2,0};
int[] temp = new int[arr.length];
mergeSort(arr,0,arr.length-1,temp);
System.out.println(Arrays.toString(arr));
}
//分解并且合并
public static void mergeSort(int[] arr,int left,int right,int[] temp){
if (left < right){
int mid = (left+right)/2;
mergeSort(arr,left,mid,temp);
mergeSort(arr,mid+1,right,temp);
merge(arr,left,mid,right,temp);
}
}
/**
* 合并
* @param arr 原来的数组
* @param left 拆分的左边序列的初始索引
* @param mid 拆分的左边序列的结束索引
* @param right 拆分的右边序列的结束索引
* @param temp 用来做中转的数组
*/
public static void merge(int[] arr ,int left,int mid,int right,int[] temp){
int i = left;
int j = mid + 1;
int t = 0;
//将序列的数组中数据按顺序放到临时数组中
while (i <= mid && j <= right){
if (arr[i] <= arr[j]){
temp[t++] = arr[i++];
}else {
temp[t++] = arr[j++];
}
}
//将剩余的数据依次放到临时数组中
while (i <= mid){
temp[t++] = arr[i++];
}
while (j <= right){
temp[t++] = arr[j++];
}
//copy临时数组数据到原来数组相同的位置
t = 0;
int tempLeft = left;
System.out.println("tempLeft="+tempLeft+",right="+right);
while (tempLeft <= right){
arr[tempLeft++] = temp[t++];
}
}
}
four radix sort
Using a two-dimensional array to save the sorted elements is to split a number into one-digit numbers for comparison and sorting
The size of the two-dimensional array is ten, and the corresponding index is exactly the value corresponding to each digit. You need to find the maximum value in the array first, and then determine the number of digits of the maximum value to determine how many times to compare and sort
At this time, a one-dimensional array is also needed to determine the valid data in each one-dimensional array in the two-dimensional array, so as to facilitate the retrieval of data from the two-dimensional array to the original array
The principle is to compare the size of one digit and sort it. The idea is very simple, but the code implementation still needs to think carefully
code show as below:
//基数排序(桶排序的优化)
public class RadixSort {
public static void main(String[] args) {
int[] arr = {
542,3,652,784,69,123,15};
radixSort(arr);
}
public static void radixSort(int[] arr){
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max){
max = arr[i];
}
}
int maxLenth = String.valueOf(max).length();
int[][] bucket = new int[10][arr.length];
//每个桶中记录的有效元素个数
int[] bucketEleCounts = new int[10];
for (int k = 0,n = 1; k < maxLenth; k++,n *= 10) {
//将原来数组元素放到桶中
for (int i = 0; i < arr.length; i++) {
int num = arr[i] / n % 10;
bucket[num][bucketEleCounts[num]++] = arr[i];
}
int index = 0;//记录原来数组的索引值
//将桶中数据再依次放到原来数组中
for (int i = 0; i < bucket.length; i++) {
if (bucketEleCounts[i] != 0){
for (int j = 0; j < bucketEleCounts[i]; j++) {
arr[index++] = bucket[i][j];
}
}
bucketEleCounts[i] = 0;
}
System.out.println("第"+k+"次排序后的数组:"+ Arrays.toString(arr));
}
}
}
Five Heap Sort
The heap sort is written at the end because it is the only algorithm among these types that needs to use the idea of the tree data structure. It may be difficult for some friends who have not been in touch with trees to understand.
We need to know what heap sort needs to use?
Heap sorting is to convert a sequentially stored binary tree into a heap structure. Generally, a large top heap is used for ascending order, that is, the parent node of the leaf node is larger than the leaf node; a small top heap is used for descending order, that is, the parent node of the leaf node is larger than the leaf node. nodes are small
Then we have to ask what is a binary tree for sequential storage. What we need to know is that the two data structures of binary tree and array can be converted to each other.
Sequential storage of binary trees
Store binary tree structure data in the form of arrays
1) Sequential storage of binary trees usually only considers complete binary trees
Complete binary tree:
There are k-level tree structures, in which all nodes are full except for the k-th level, and try to ensure that the left subtree of the k-th level is full of nodes
2) The left child node of the nth element is 2*n+1
3) The right child node of the nth element is 2*n+2
4) The parent node of the nth element is (n-1)/2
Maybe after talking so much, some friends still don’t understand it very well. Next, I will show it in a graphical way.
The specific conversion process is as follows:
The specific steps for converting a binary tree to a large top heap:
①Compare the parent node of the last element with the left and right child nodes, and exchange the largest element with the parent node
② Then use the current node as the root node to judge whether the subtrees of the left and right child nodes meet the conditions of the big top heap, and then judge down in order to ensure that all the subtrees under the current node as the root node meet the conditions of the big top heap
After the end of the round, the root node is exchanged with the last element, and the length is reduced by one, that is, the largest element arranged is excluded, and this element will not be considered in subsequent operations
Repeat the above process of converting the big top heap again until all the elements are sorted
You can follow the code according to the diagram, and you should have a deeper understanding
Next is the code:
public class HeapSort {
public static void main(String[] args) {
int[] arr = {
4,6,8,5,9,99,13,-6,-66,98,123};
heapSort(arr);
}
public static void heapSort(int[] arr){
int temp = arr[0];
//找出最大的值放在堆的根节点
for (int i = arr.length/2 -1; i >= 0 ; i--) {
adjustHeap(arr,i,arr.length);
}
//交换根节点与最后一个节点的位置并移除最后一个节点
for (int i = arr.length-1; i > 0 ; i--) {
temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
adjustHeap(arr,0,i);
}
System.out.println(Arrays.toString(arr));
}
/**
* 将数组转换为大顶堆
*
* @param arr 要转换的数组
* @param i 非叶子结点在数组中的索引
* @param length 表示对多少个元素进行调整
*/
public static void adjustHeap(int[] arr,int i,int length){
int temp = arr[i];
for (int j = 2 * i + 1; j < length; j = 2 * j + 1) {
if (j+1 < length && arr[j] < arr[j+1]){
j++;
}
if (arr[j] > temp){
arr[i] = arr[j];
i = j;
}else {
break;
}
}
arr[i] = temp;
}
}
To be honest, it is a bit difficult to understand. I have thought about it for a long time. It may be that my level is not enough to explain it in an easy-to-understand manner. I hope that some big guys can help point out any problems or what can be improved.
After reading it, if you feel that it is helpful to you, you can give it a thumbs up. This is the first time you have written an article with tens of thousands of words. I hope you understand if you have any questions.