归并排序 (Merge Sort)
归并排序是一种有效的排序算法,采用分治法的一个典型应用。它将数组分成两半,对每部分递归地应用归并排序,然后将排序后的部分合并。在处理大数据集时,归并排序特别有效,因为它的时间复杂度,并且它对数据的分布不敏感(即对于大小不同的数据集始终保持相同的性能)。
python代码实现(带有随机数据)
data = [25, 57, 24, 66, 25, 19, 90, 84, 38, 80, 7, 33, 96, 71, 6, 99, 99, 29, 63, 65, 49, 75, 88, 90, 46, 53, 36, 55, 9, 42, 13, 3, 52, 31, 0, 71, 88, 89, 90, 10, 58, 49, 40, 62, 0, 81, 5, 93, 91, 97] def merge_sort(arr): if len(arr) > 1: # 找到数组的中间点并分割成左右两部分 mid = len(arr) // 2 L = arr[:mid] R = arr[mid:] # 递归调用归并排序来分别排序左右两部分 merge_sort(L) merge_sort(R) i = j = k = 0 # 将数据从两个临时数组复制回原数组arr while i < len(L) and j < len(R): if L[i] < R[j]: arr[k] = L[i] i += 1 else: arr[k] = R[j] j += 1 k += 1 # 检查是否有剩余元素 while i < len(L): arr[k] = L[i] i += 1 k += 1 while j < len(R): arr[k] = R[j] j += 1 k += 1 # 对数据进行归并排序 merge_sort(data) print("排序后的数据:", data)
c代码实现
#include <stdio.h> #include <stdlib.h> void merge(int arr[], int l, int m, int r) { int i, j, k; int n1 = m - l + 1; int n2 = r - m; // 创建临时数组 int L[n1], R[n2]; // 拷贝数据到临时数组L[]和R[] for (i = 0; i < n1; i++) L[i] = arr[l + i]; for (j = 0; j < n2; j++) R[j] = arr[m + 1 + j]; // 将临时数组的数据合并回arr[l..r] i = 0; j = 0; k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } // 拷贝L[]中的剩余元素 while (i < n1) { arr[k] = L[i]; i++; k++; } // 拷贝R[]中的剩余元素 while (j < n2) { arr[k] = R[j]; j++; k++; } } void mergeSort(int arr[], int l, int r) { if (l < r) { // 找到中间点 int m = l + (r - l) / 2; // 分别对左半部和右半部进行归并排序 mergeSort(arr, l, m); mergeSort(arr, m + 1, r); // 合并两半 merge(arr, l, m, r); } } /* 用于打印数组 */ void printArray(int A[], int size) { int i; for (i = 0; i < size; i++) printf("%d ", A[i]); printf(" "); } /* 测试归并排序程序 */ int main() { int arr[] = {12, 11, 13, 5, 6, 7}; int arr_size = sizeof(arr) / sizeof(arr[0]); printf("给定的数组是 "); printArray(arr, arr_size); mergeSort(arr, 0, arr_size - 1); printf(" 排序后的数组是 "); printArray(arr, arr_size); return 0; }
具体实现步骤
以下是归并排序的具体步骤:
-
分割:首先将数组递归地分割成两半,直到每个子数组只有一个元素或为空。
-
合并:然后将这些子数组合并起来,形成一个有序的数组。
让我们更详细地分析这个过程:
分割步骤
- 开始时,你有一个未排序的数组。
- 将数组从中间分割成两部分,如果数组有奇数个元素,其中一个部分将多出一个元素。
- 对这两个子数组递归地执行相同的分割操作,直到每个子数组只包含一个元素或为空。这时,每个子数组都被认为是有序的。
合并步骤
- 一旦你有了一系列有序的子数组,你就开始将它们合并在一起,以形成更大的有序数组。
- 在合并过程中,你从两个子数组的起始位置开始,比较它们的元素。将较小的元素先放入新的数组中,然后移动到下一个元素。
- 如果一个子数组的所有元素都被选中了,而另一个子数组还有剩余元素,那么剩余的元素将直接被复制到新数组的末尾。
- 这个过程重复进行,直到所有的子数组都被合并成一个完整的、有序的数组。
归并排序的效率来自于它能够保持 的时间复杂度,无论数据的初始排序状态如何。这使得它在处理大型数据集时非常有效。此外,归并排序是一种稳定的排序算法,这意味着具有相同键值的元素在排序后的数组中将保持原有的顺序。