From fb84ed904dc79a786969184abac077efe9333a67 Mon Sep 17 00:00:00 2001 From: luojunll Date: Tue, 16 Jul 2024 15:12:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BD=92=E5=B9=B6=E6=8E=92=E5=BA=8F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vuepress/sidebar.ts | 1 + ...22\345\271\266\346\216\222\345\272\217.md" | 212 ++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 "docs/code/\347\256\227\346\263\225/\345\275\222\345\271\266\346\216\222\345\272\217.md" diff --git a/docs/.vuepress/sidebar.ts b/docs/.vuepress/sidebar.ts index e39a697..8dfb294 100644 --- a/docs/.vuepress/sidebar.ts +++ b/docs/.vuepress/sidebar.ts @@ -39,6 +39,7 @@ export default sidebar({ collapsible: true, children: [ '希尔排序.md', + '归并排序.md' ], }, ] diff --git "a/docs/code/\347\256\227\346\263\225/\345\275\222\345\271\266\346\216\222\345\272\217.md" "b/docs/code/\347\256\227\346\263\225/\345\275\222\345\271\266\346\216\222\345\272\217.md" new file mode 100644 index 0000000..36b34a8 --- /dev/null +++ "b/docs/code/\347\256\227\346\263\225/\345\275\222\345\271\266\346\216\222\345\272\217.md" @@ -0,0 +1,212 @@ +--- +title: 归并排序 +date: 2024-07-16 +category: + - 代码编程 + - 算法 +tag: + - 算法 +sticky: true +star: true +order: -1 +--- + +# 归并排序 + +## 介绍 +**归并排序**(*Merge Sort*)是一种基于分治法的排序算法。它的主要思想是将一个大的问题分解成若干个小问题来解决,然后将解决的结果合并在一起。归并排序的时间复杂度为 𝑂(𝑛log𝑛),是效率较高的排序算法之一。 + +## 代码 + +### 迭代 +1. C +``` +#include +#include + +int min(int x, int y) +{ + return x < y ? x : y; +} + +void merge_sort(int arr[], int len) +{ + int *a = arr; + int *b = (int *)malloc(len * sizeof(int)); + if (b == NULL) + { + fprintf(stderr, "Memory allocation failed\n"); + return; + } + int seg, start; + for (seg = 1; seg < len; seg += seg) + { + for (start = 0; start < len; start += seg + seg) + { + int low = start, mid = min(start + seg, len), high = min(start + 2 * seg, len); + int k = low; + int start1 = low, end1 = mid; + int start2 = mid, end2 = high; + while (start1 < end1 && start2 < end2) + b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++]; + while (start1 < end1) + b[k++] = a[start1++]; + while (start2 < end2) + b[k++] = a[start2++]; + } + int *temp = a; + a = b; + b = temp; + } + if (a != arr) + { + for (int i = 0; i < len; i++) + arr[i] = a[i]; + } + free(b); +} + +int main() +{ + int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70}; + int len = sizeof(arr) / sizeof(*arr); + merge_sort(arr, len); + for (int i = 0; i < len; i++) + printf("%d ", arr[i]); + printf("\n"); + return 0; +} +``` + +2. Python +``` +def min(x, y): + return x if x < y else y + +def merge_sort(arr): + n = len(arr) + a = arr[:] + b = [0] * n + seg = 1 + while seg < n: + for start in range(0, n, seg + seg): + low = start + mid = min(start + seg, n) + high = min(start + seg + seg, n) + k = low + start1 = low + end1 = mid + start2 = mid + end2 = high + while start1 < end1 and start2 < end2: + if a[start1] < a[start2]: + b[k] = a[start1] + start1 += 1 + else: + b[k] = a[start2] + start2 += 1 + k += 1 + while start1 < end1: + b[k] = a[start1] + start1 += 1 + k += 1 + while start2 < end2: + b[k] = a[start2] + start2 += 1 + k += 1 + a, b = b, a + seg += seg + + if a != arr: + for i in range(n): + arr[i] = a[i] + +arr = [38, 27, 43, 3, 9, 82, 10] +merge_sort(arr) +print(arr) +``` +3. #### 分析 +先将数组分为1个为一组,分了7组, 再1,2;3,4;5,6;7;两两比较,给比较的两组定义一个指针,指针所指的值相互比较, 也就是在这个块`while start1 < end1 and start2 < end2`进行,小的值排左边,直到有一组的指针指向了末尾;如果剩的是第一组的就调用`while start1 < end1`这个块,否则调用`while start2 < end2`这个块。以此类推,分成4组, 分成2组......最终得到有序的数列。 + +## 递归 +1. C +``` +#include +#include // 加入此行以便使用 malloc 和 free + +void merge_sort_recursive(int arr[], int reg[], int start, int end) { + if (start >= end) + return; + int len = end - start, mid = (len >> 1) + start; + int start1 = start, end1 = mid; + int start2 = mid + 1, end2 = end; + merge_sort_recursive(arr, reg, start1, end1); + merge_sort_recursive(arr, reg, start2, end2); + int k = start; + while (start1 <= end1 && start2 <= end2) + reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++]; + while (start1 <= end1) + reg[k++] = arr[start1++]; + while (start2 <= end2) + reg[k++] = arr[start2++]; + for (k = start; k <= end; k++) + arr[k] = reg[k]; +} +void merge_sort(int arr[], const int len) { + int reg[len]; + merge_sort_recursive(arr, reg, 0, len - 1); +} + +int main() { + int arr[] = { 22, 34, 3, 32, 82, 55, 89 }; + int len = sizeof(arr) / sizeof(*arr); + merge_sort(arr, len); + for (int i = 0; i < len; i++) + printf("%d ", arr[i]); + printf("\n"); // 增加换行以美化输出 + return 0; +} +``` + +2. Python +``` +def merge_sort_recursive(arr, reg, start, end): + if start >= end: + return + mid = (start + end) // 2 + merge_sort_recursive(arr, reg, start, mid) + merge_sort_recursive(arr, reg, mid + 1, end) + start1, end1 = start, mid + start2, end2 = mid + 1, end + k = start + while start1 <= end1 and start2 <= end2: + if arr[start1] < arr[start2]: + reg[k] = arr[start1] + start1 += 1 + else: + reg[k] = arr[start2] + start2 += 1 + k += 1 + while start1 <= end1: + reg[k] = arr[start1] + start1 += 1 + k += 1 + while start2 <= end2: + reg[k] = arr[start2] + start2 += 1 + k += 1 + for k in range(start, end + 1): + arr[k] = reg[k] + +def merge_sort(arr): + reg = [0] * len(arr) + merge_sort_recursive(arr, reg, 0, len(arr) - 1) + +# 示例使用 +arr = [22, 34, 3, 32, 82, 55, 89] +merge_sort(arr) +print(arr) +``` + +3. ### 分析 +逻辑和迭代法差不多。 \ No newline at end of file