【算法导论】分治法及归并排序
2014-09-18 00:39
330 查看
有很多算法,在结构上他们是递归的:为了解决一个已经给定的问题,算法要一次或多次的递归调用其自身来解决相关的子问题,这类算法通常采用分治策略。
分治法的基本思想:
(1).原问题==(划分)== >>若干个更小规模的子问题。
(2).要求子问题的求解方法与原问题相同。
分治法的求解步骤:
(1)分解(Divide):将当前问题划分成若干子问题
(2)解决(Conquer):递归解子问题,如果子问题足够小则直接解
(3)合并(Combine):将子问题的解合并长原问题
分治法示例,归并排序:
在merge()函数中,第70行~77行的的for()循环所需要的时间O(n1+n2)=O(n),第86行~98行的for循环共有n轮迭代,其中每一轮迭代所需的时间都是常量,所以merge()函数的时间复杂度为O(n)。
分治法的基本思想:
(1).原问题==(划分)== >>若干个更小规模的子问题。
(2).要求子问题的求解方法与原问题相同。
分治法的求解步骤:
(1)分解(Divide):将当前问题划分成若干子问题
(2)解决(Conquer):递归解子问题,如果子问题足够小则直接解
(3)合并(Combine):将子问题的解合并长原问题
分治法示例,归并排序:
/* 《Introduction to Algorithms(second edition)》 chapter2,MERGE_SORT() date:2014-9-18 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #define MAX 50 typedef struct { int arr[MAX+1]; int length; }SortArr; SortArr *CreateSortArr() { int i = 0; char buf[4*MAX] = ""; char *ptr = NULL; SortArr *sortArr = (SortArr *)malloc(sizeof(SortArr)); memset(sortArr, 0, sizeof(SortArr)); printf("请输入待排序数据,以逗号分隔,以分号结束\n" "例:23,12,65,36,35;\n" "input:"); scanf("%s", buf); ptr = buf; sortArr->arr[i] = 0; //arr[0]不存值用作哨兵单元 i = 1; while(*ptr != ';') { sortArr->arr[i] = atoi(ptr); i++; ptr = strstr(ptr, ","); if(!ptr) { break; } ptr++; } sortArr->length = (i - 1); return sortArr; } int merge(int arr[], int p, int q, int r) { int i = 0; int j = 0; int k = 0; int n1 = 0; int n2 = 0; int *leftArr = NULL; int *rightArr = NULL; n1 = q - p + 1; n2 = r - q; //为了和arr[]下标保持一致,leftArr[0]和rightArr[0]不用 leftArr = (int *)malloc((n1 + 2) * sizeof(int)); rightArr = (int *)malloc((n2 + 2) * sizeof(int)); for(i = 1; i <= n1; i++) { leftArr[i] = arr[p+i-1]; } for(j = 0; j <= n2; j++) { rightArr[j] = arr[q+j]; } i = 1; j = 1; //将最后一个数设置为哨兵 leftArr[n1+1] = INT_MAX; rightArr[n2+1] = INT_MAX; for(k = p; k <= r; k++) { if(leftArr[i] <= rightArr[j]) { arr[k] = leftArr[i]; i++; } else { arr[k] = rightArr[j]; j++; } } free(leftArr); free(rightArr); return 0; } int mergeSort(int arr[], int p, int r) { int q = 0; if(p < r) { q = (p + r) / 2; mergeSort(arr, p, q); mergeSort(arr, (q+1), r); merge(arr, p, q, r); } return 0; } int MergingSortRecursion(SortArr *sortArr) { mergeSort(sortArr, 1, sortArr->length); return 0; } int PrintArray(SortArr sortArr) { int i = 0; for(i = 1; i <= sortArr.length; i++) { printf("%d,", sortArr.arr[i]); } printf("\b;\n"); return 0; } int main() { SortArr *sortArr = NULL; sortArr = CreateSortArr(); printf("\nBefore Sort:\t"); PrintArray(*sortArr); MergingSortRecursion(sortArr); printf("Sorted Array:\t"); PrintArray(*sortArr); free(sortArr); return 0; }时间复杂度分析:
在merge()函数中,第70行~77行的的for()循环所需要的时间O(n1+n2)=O(n),第86行~98行的for循环共有n轮迭代,其中每一轮迭代所需的时间都是常量,所以merge()函数的时间复杂度为O(n)。
相关文章推荐
- 【算法导论】2-2 二路归并排序(分治)merge-sort 和逆序对的问题
- 算法导论2.3.2--归并排序
- 算法导论学习笔记(2)-归并排序
- 【python菜鸟日记】-03算法导论-归并排序
- 【算法学习】归并排序——基于分治思想
- 分治思想的几个算法:二分检索、快排、归并排序
- 算法基础:分治模式,归并排序ΘΘΘΘΘΘ知识小结
- 算法导论之排序:快速排序、归并排序、计数排序、基数排序、桶排序
- 【算法导论学习-002】归并排序(MergeSort)
- 【算法导论】第二章之归并排序
- 归并排序的C语言实现【严蔚敏+算法导论】
- 从零开书学算法(导论)之归并排序
- 一头扎进算法导论-归并排序
- 算法导论1:插入排序和归并排序 2016.1.1
- 求最大子数组的和,算法导论之分治递归求解,暴力求解,记忆扫描方法。
- 算法导论实验四_分治法求平面上的最小点对
- <菜鸟学算法-A排序(分治的思想:归并排序)>
- 再读算法导论关于归并排序