网站首页 > 文章精选 正文
分治算法的思想到底是什么?能不能用通俗易懂的方式讲解一下?
分治算法是一种重要的算法设计策略,其核心思想是"分而治之",即将一个大问题分解成若干个相似的子问题,递归求解子问题,最后合并子问题的解得到原问题的解。
1.基本思想
1)分治算法的基本思想
分治算法通常包含三个步骤:
- 分解(Divide):将原问题分解成若干个规模较小的子问题。
- 解决(Conquer):递归求解子问题。如果子问题足够小,则直接求解。
- 合并(Combine):将子问题的解合并,得到原问题的解。
分治算法 =分(Divide) +治(Conquer) +合(Combine)
- 分解原则:
- 子问题必须与原问题同构(相同性质)
- 子问题之间应尽可能独立
- 分解后的规模应显著减小(通常至少减半)
2)递归方程建立
通用形式:
T(n)=a·T(nb)+f(n)
其中:
- a:子问题数量
- nb:子问题规模
- f(n):分解+合并的代价
2.归并排序
归并排序是一种基于分治思想的经典排序算法,其时间复杂度为O(nlogn),是稳定排序算法。
示例:假设要排序数组是[38, 27, 43, 3, 9, 82, 10]
第一步:分解过程(分)
原始数组: [38, 27, 43, 3, 9, 82, 10]第一次分割: [38, 27, 43, 3] 和 [9, 82, 10]第二次分割: [38, 27] 和 [43, 3] [9, 82] 和 [10]第三次分割: [38] 和 [27] [43] 和 [3] [9] 和 [82] [10] (已经是最小单元)
第二步:合并过程(合)
合并 [38] 和 [27] → [27, 38]合并 [43] 和 [3] → [3, 43]合并 [27, 38] 和 [3, 43] → [3, 27, 38, 43] (左半部分完成)合并 [9] 和 [82] → [9, 82]合并 [9, 82] 和 [10] → [9, 10, 82] (右半部分完成)最后合并 [3, 27, 38, 43] 和 [9, 10, 82] → [3, 9, 10, 27, 38, 43, 82]
实现代码如下:
#include#includeusing namespace std;void merge(vector<int>& arr,int left,int mid,int right){ std::vector<int> L(arr.begin() + left, arr.begin() + mid + 1); std::vector<int> R(arr.begin() + mid + 1, arr.begin() + right + 1); int i = 0, j = 0, k = left; // 比较两个数组的元素,取较小的放入原数组 while (i < L.size() && j < R.size()) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } // 将剩余元素拷贝到原数组 while (i < L.size()) { arr[k] = L[i]; i++; k++; } while (j < R.size()) { arr[k] = R[j]; j++; k++; } }void merge_sort(vector<int>& arr,int left,int right){ if(left>=right){ return; } //因为是递归,left 在非首次可能不是0,所以mid 如下式 int mid = left + (right - left)/2; merge_sort(arr,left,mid); merge_sort(arr,mid+1,right); merge(arr,left,mid,right); }int main(){ vector<int> array ={1,3,9,2,4,5,7}; merge_sort(array,0,array.size()-1); for (int num : array) { std::cout << num << " "; } }
3.快速排序
快速排序是一种高效的排序算法,采用分治策略,平均时间复杂度为O(n log n),最坏情况下为O(n^2)。核心思想:选一个数,小的放左边,大的放右边,递归搞定。
算法步骤:
1.选择基准值(pivot):从数组中选择一个元素作为基准
2.分区(partition):将数组分为两部分,使得:
- 左边部分的元素都小于等于基准值
- 右边部分的元素都大于基准值
3.递归排序:对左右两部分递归地应用快速排序。
示例:初始数组: [38, 27, 43, 3, 9, 82, 10]
第一次分区(pivot=10)将 ≤10 的数移到左边,>10 的数留在右边:交换后:[3, 9, 10, 27, 38, 82, 43]分区结果:[3, 9] 和 [27, 38, 82, 43](基准值 10 已归位)递归处理左子数组 [3, 9](pivot=9)分区后:[3, 9](已有序)递归处理右子数组 [27, 38, 82, 43](pivot=43)分区后:[27, 38, 43, 82]进一步分割:[27, 38] 和 [82]最终排序结果: [3, 9, 10, 27, 38, 43, 82]
实现代码如下:
#include#includeusing namespace std;void quick_sort(vector<int>& arr, int low, int high) { if (low >= high) return; // 递归终止条件 int pivot = arr[high]; // 选最右为基准 int i = low - 1; // i标记≤pivot的边界 for (int j = low; j < high; j++) { if (arr[j] <= pivot) { i++; swap(arr[i], arr[j]); // 把小的数换到左边 } } swap(arr[i + 1], arr[high]); // 把基准放到正确位置 // 递归排序左右两部分 quick_sort(arr, low, i); // 排序左边 quick_sort(arr, i + 2, high); // 排序右边}int main(){ vector<int> array ={38, 27, 43, 3, 9, 82, 10}; quick_sort(array,0,array.size()-1); for (int num : array) { std::cout << num << " "; } }
总结:分治法的核心是“分而治之”:通过递归分解问题→解决子问题→合并结果,将复杂问题化繁为简。
典型代表:快速排序、归并排序。
猜你喜欢
- 2025-06-24 算法基础:插入排序 实现原理和应用场景
- 2025-06-24 基础数据结构——八大排序详解(数据结构八种排序算法的思想)
- 2025-06-24 C#程序员必知:如何让你的代码跑得比火箭还快!深度优化实践指南
- 2025-06-24 数据结构与算法之道:解读常数、线性、对数时间复杂度!
- 2025-06-24 排序算法—快速排序(快速排序算法总结)
- 2025-06-24 Python高级排序算法应用(python3 排序算法)
- 2025-06-24 大数据高频面试题之算法题(大数据技术之高频面试题)
- 2025-06-24 用Python实现十大经典排序算法-插入、选择、快速、冒泡、归并等
- 2025-06-24 面试常考八股文及算法(一)(八股文的要求)
- 2025-06-24 技术分享:这可能最快的稳定排序算法
- 06-24PLC常用进制数及转换方法(plc中进制符号)
- 06-24PLC常用数制及转换方法,让你轻松掌握PLC编程
- 06-24PLC编程必看!5种常见进制数解析,搞懂才能玩转PLC!
- 06-24C数据类型——常量(c的数据类型及其定义方法)
- 06-24什么是二进制、八进制、十进制、十六进制?
- 06-24理论基础——十进制、二进制、十六进制、八进制
- 06-24搞不懂PLC中的高字节、低字位是啥?看完这篇文章就懂了!
- 06-242、进位制之间的转换(含有小数位)
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)