在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如
排序算法(
快速排序,
归并排序)。
分解:把数组从中间分解为2个子数组
解决:递归解决子数组
合并:合并数据
1 static void Main(string[] args) 2 { 3 int[] ints = { 3, 1, 5, 2, 4,9,-4 }; 4 5 ArrayList arr = new ArrayList(ints); 6 Sort(arr); 7 for (int i = 0; i < arr.Count; i++) 8 { 9 Console.WriteLine(arr[i]); 10 } 11 Console.ReadLine(); 12 } 13 /// <summary> 14 /// 分组排序 15 /// </summary> 16 /// <param name="arr"></param> 17 /// <returns></returns> 18 public static ArrayList Sort(ArrayList arr) 19 { 20 ArrayList arr_l = new ArrayList(); 21 ArrayList arr_r = new ArrayList(); 22 if (arr.Count > 1) 23 { 24 for (int i = 0; i < arr.Count; i++) 25 { 26 int num = arr.Count / 2; 27 28 if (i < num) 29 arr_l.Add(arr[i]); 30 else 31 arr_r.Add(arr[i]); 32 } 33 34 ArrayList part1 = Sort(arr_l);//分组1 35 ArrayList part2 = Sort(arr_r);//分组2 36 Merger(part1, part2, arr); 37 } 38 39 return arr; 40 } 41 /// <summary> 42 /// 合并 43 /// </summary> 44 /// <param name="arr_l">左</param> 45 /// <param name="arr_r">右</param> 46 /// <param name="arr">数据集</param> 47 public static void Merger(ArrayList arr_l, ArrayList arr_r, ArrayList arr) 48 { 49 int l = 0;//左索引 50 int r = 0;//右索引 51 int index = 0;//数据集索引 52 53 while (l < arr_l.Count && r < arr_r.Count) 54 { 55 if ((int)arr_l[l] <= (int)arr_r[r]) 56 { 57 arr[index] = (int)arr_l[l]; 58 l++; 59 } 60 else 61 { 62 arr[index] = (int)arr_r[r]; 63 r++; 64 } 65 index++; 66 } 67 while (l < arr_l.Count) 68 { 69 arr[index] = (int)arr_l[l]; 70 index++; 71 l++; 72 } 73 74 while (r < arr_r.Count) 75 { 76 arr[index] = (int)arr_r[r]; 77 index++; 78 r++; 79 } 80 81 }
分解图
时间分析
分解:把数组从中间分解为2个子数组需要常量c
解决:递归解决规模n/2子数组需要lgn+1
合并:合并数据需要常量n
每一层运算时间为cn,总时间为cn(lgn+1);忽略常量c得到结果nlgn
效果图
结束语
程序存在着一些不足,操作比较复杂,时间解释一块自己也无法完美表达,也可能存在理解误差,希望给出指导意见
请多多指教!