Article directory
1. Merge sort
1. Concept
It is an effective and stable sorting algorithm based on the merge operation. This algorithm is a very typical application using the divide and conquer method (Divide and Conquer). Merge the already ordered subsequences to obtain a completely ordered sequence; that is, first make each subsequence orderly, and then make the subsequence segments orderly. If two ordered lists are merged into one ordered list, it is called a two-way merge.
2. Process
Assumption:
Left half interval->ordered
Right half interval->ordered
How to sort left and right?
When there is only one element left, we can default to it being ordered, so we can use recursion to divide the elements in the array into one, and then merge the two groups into two groups, and so on.
Merge, compare the smaller ones in order and put them into the new temporary array. After completing the sorting, copy the data of the temporary array back to the original array
Process chart:
3. Code implementation
recursion:
void Print(int* arr, int n) {
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
}
//递归
void _MergeSort(int *a,int *t,int left,int right) {
//结束条件
if (left >= right)
return;
int mid = (left + right) >> 1;//取中间数,划分区间
//[left mid] [mid+1 right]
//递归
_MergeSort(a, t, left, mid);
_MergeSort(a, t, mid + 1, right);
//回归
int begin1 = left, end1 = mid;//左区间
int begin2 = mid + 1 , end2 = right;//右区间
//临时数组下标->对应的是数组a的下标
int index = left;
//当左区间或者右区间,遍历完了就结束了
while (begin1 <= end1 && begin2 <= end2) {
//选择小的放进临时数组
if (a[begin1] < a[begin2])
t[index++] = a[begin1++];
else
t[index++] = a[begin2++];
}
//判断左右两边是否都空了,不为空将后面补上
while (begin1 <= end1)
t[index++] = a[begin1++];
while (begin2 <= end2)
t[index++] = a[begin2++];
//最后拷贝回去
for (int i = left; i <= right; ++i)
a[i] = t[i];
}
void MergeSort(int* a, int n) {
int* t = (int*)malloc(sizeof(int) * n);
_MergeSort(a, t, 0, n - 1);
free(t);
}
int main() {
int a[] = {
3,7,1,0,9,6,2,3,8,5 };
MergeSort(a, sizeof(a) / sizeof(a[0]));
Print(a, sizeof(a) / sizeof(a[0]));
return 0;
}
Recursive graph (left, first recursive and then recursive):
Non-recursive:
We implement non-recursion through loops
(1) Set a gap to divide the number of merges, first set gap=1 , in this way, the first time the control is to merge two numbers, the gap is multiplied by 2 to increment, and it ends when gap>n (array size)
(2) Two numbers may appear during the merging process. Situation
a. There is no element on the right during the merging process
such as:
Solution: Because it has been arranged, just break it Just loop
b. There are elements on the right but not enough
such as:
Solution: Make corrections and change the subscript on the right end Change to n-1 (array size-1)
Code:
//非递归
void MergeSortNonR(int* a, int* t,int n) {
int gap= 1;//划分一次归并多少个元素
//结束条件
while (gap<n) {
for (int i = 0; i < n; i += 2*gap) {
//通过gap划分区间
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + gap * 2 - 1;
//情况a,此时直接打破即可
if (begin2 >= n)
break;
//情况b,进行纠正
if (end2 >= n)
end2 = n - 1;
int index = i;//从控制的区间最小的位置开始
//下面过程与递归过程一样
while (begin1 <= end1 && begin2 <= end2) {
if (a[begin1] < a[begin2])
t[index++] = a[begin1++];
else
t[index++] = a[begin2++];
}
while (begin1 <= end1)
t[index++] = a[begin1++];
while (begin2 <= end2)
t[index++] = a[begin2++];
for (int j = i; j <= end2; j++)
a[j] = t[j];
}
gap *= 2;//每次加倍
}
}
void MergeSort(int* a, int n) {
int* t = (int*)malloc(sizeof(int) * n);
MergeSortNonR(a, t, n);
free(t);
}
int main() {
int a[] = {
6,3,7,1,9,5,2,8,0,4 };
MergeSort(a, sizeof(a) / sizeof(a[0]));
Print(a, sizeof(a) / sizeof(a[0]));
return 0;
}
4. Complexity
Time complexity:
(1) Loop part: N
(2) Recursive part: Because it is halved every time, it is logN ( Taking base 2)
So the time complexity is: O(N*logN)
Space complexity:
Because it is necessary Re-open an array, so the space complexity is O(N)
5. Stability
The order of the same elements will not change during the merging process, so it is stable.
2. Counting sorting
1. Ideas
Count the number of occurrences of each number through mapping, and then use the number of times to sort
For example:
The above is to create a space with the maximum number Solution: Find the range , use range +1 to create temporary space For example:
But if we encounter a large number, we need to create space, which will be very wasteful
2. Code implementation
//计数排序
void CountSort(int* a, int n) {
int max = a[0];
int min = a[0];
//求出数组的范围
for (int i = 0; i < n; i++) {
if (max < a[i])
max = a[i];
if (min > a[i])
min = a[i];
}
int t = max - min+1;
//临时空间
int* p = (int*)calloc(t,sizeof(int));
//统计个数
for (int j = 0; j < n; j++) {
//a[j]-min当下标,我们下次直接加回min即可
p[a[j] - min]++;
}
int i = 0;
//按顺序拷贝回原来的数组
for (int j = 0; j < t; j++) {
while (p[j]) {
a[i] = j + min;
i++;
p[j]--;
}
}
free(p);
p = NULL;
}
3. Complexity:
Space complexity: Because a temporary space needs to be created, the complexity is O(N);
Time complexity: O(N+t)
4. Stability
During the statistics and reordering process, the positions of the same elements may be exchanged, so it is unstable.
The above is what I shared. If there are any mistakes, please leave a message in the comment area.
Finally, thank you everyone for watching!