分治算法凸包
❶ 什么是分治算法
分治法就是将一个复杂的问题分成多个相对简单的独立问题进行求解,并且综合所有简单问题的解可以组成这个复杂问题的解。
例如快速排序算法就是一个分治法的例子。即将一个大的无序序列排序成有序序列,等于将两个无序的子序列排序成有序,且两个子序列之间满足一个序列的元素普遍大于另一个序列中的元素。
❷ 分治法的步骤
分治法在每一层递归上都有三个步骤:
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
合并:将各个子问题的解合并为原问题的解。
它的一般的算法设计模式如下:
Divide-and-Conquer(P)
1. if |P|≤n0
2. then return(ADHOC(P))
3. 将P分解为较小的子问题 P1 ,P2 ,...,Pk
4. for i←1 to k
5. do yi ← Divide-and-Conquer(Pi) △ 递归解决Pi
6. T ← MERGE(y1,y2,...,yk) △ 合并子问题
7. return(T)
其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)求解。算法MERGE(y1,y2,...,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,...,Pk的相应的解y1,y2,...,yk合并为P的解。
根据分治法的分割原则,原问题应该分为多少个子问题才较适宜?
各个子问题的规模应该怎样才为适当?
答: 但人们从大量实践中发现,在用分治法设计算法时,最好使子问题的规模大致相同。换句话说,将一个问题分成大小相等的k个子问题的处理方法是行之有效的。许多问题可以取 k = 2。这种使子问题规模大致相等的做法是出自一种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。
出处:网络
实践题目:
给定一个顺序表,编写一个求出其最大值和最小值的分治算法。
分析:
由于顺序表的结构没有给出,作为演示分治法这里从简顺序表取一整形数组数组大小由用户定义,数据随机生成。我们知道如果数组大小为 1 则可以直接给出结果,如果大小为 2则一次比较即可得出结果,于是我们找到求解该问题的子问题即: 数组大小 <= 2。到此我们就可以进行分治运算了,只要求解的问题数组长度比 2 大就继续分治,否则求解子问题的解并更新全局解
以下是代码。
*/
/*** 编译环境TC ***/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define M 40
/* 分治法获取最优解 */
void PartionGet(int s,int e,int *meter,int *max,int *min){
/* 参数:
* s 当前分治段的开始下标
* e 当前分治段的结束下标
* meter 表的地址
* max 存储当前搜索到的最大值
* min 存储当前搜索到的最小值
*/
int i;
if(e-s <= 1){ /* 获取局部解,并更新全局解 */
if(meter[s] > meter[e]){
if(meter[s] > *max)
*max = meter[s];
if(meter[e] < *min)
*min = meter[e];
}
else{
if(meter[e] > *max)
*max = meter[e];
if(meter[s] < *min)
*min = meter[s];
}
return ;
}
i = s + (e-s)/2; /* 不是子问题继续分治,这里使用了二分,也可以是其它 */
PartionGet(s,i,meter,max,min);
PartionGet(i+1,e,meter,max,min);
}
int main(){
int i,meter[M];
int max = INT_MIN; /* 用最小值初始化 */
int min = INT_MAX; /* 用最大值初始化 */
printf(The array's element as followed:
);
rand(); /* 初始化随机数发生器 */
for(i = 0; i < M; i ++){ /* 随机数据填充数组 */
meter[i] = rand()%10000;
if(!((i+1)%10)) /* 输出表的随机数据 */
printf(%-6d
,meter[i]);
else
printf(%-6d,meter[i]);
}
PartionGet(0,M - 1,meter,&max,&min); /* 分治法获取最值 */
printf(
Max : %d
Min : %d
,max,min);
system(pause);
return 0;
}
❸ 凸包 支撑线
点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。下图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。
为了解决分治算法、插入算法和生长算法都要求在构网之前给出所有点数据这个问题,实时三角网剖分算法先利用部分离散点生成一个外轮廓为凸包的初始三角网.然后将点加入到既有三角网中,如点落在既有三角网的某一三角形中,将该点与三角形的顶点相连构建新的三角网;如点落在既有三角网外,找出该点向既有三角网外轮廓围成的凸包发出的两条支撑线,这两条支撑线与既有凸包围成了一个多边形,再将这个多边形剖分成三角网即可.最后利用局部优化算法对所生成的三角网进行优化,使之成为Delaunay三角网.该算法构网时无需预先给定所有数据点,可用于实时生成三角网;此外,通过对凸包进行分区管理,在搜寻凸包支撑线时,能预先确定出支撑点的范围,减少了搜索工作量,提高了三角网的生成速度.
❹ 使用分治算法解决的问题具备什么特征
分治法能解决的问题一般具有以下几个特征:
1、该问题的规模缩小到一定的程度就可以容易的解决。
2、该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3、利用该问题分解出的子问题的解可以合并为该问题的解。
4、该问题所分解出的自问题是相互独立的,即子问题之间不包含子子问题。
(4)分治算法凸包扩展阅读
思想及策略
分治算法的设计思想是:将一个难以直接解决的大问题,分割成一些规模小的相同的问题,一边各个击破,分而治之。
分治算法的策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如规模n比较小)则直接解决,否则将其分解成k个规模较小的自问题,这些子问题相互独立且与元问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
❺ 分治算法几个经典例子
分治法,字面意思是“分而治之”,就是把一个复杂的1问题分成两个或多个相同或相似的子问题,再把子问题分成更小的子问题直到最后子问题可以简单地直接求解,原问题的解即子问题的解的合并,这个思想是很多高效算法的基础。
图二
大整数乘法
Strassen矩阵乘法
棋盘覆盖
合并排序
快速排序
线性时间选择
最接近点对问题
循环赛日程表
汉诺塔
❻ 分治法指的是什么呢
分治法指的是将原问题递归地分成若干个子问题,直到子问题满足边界条件,停止递归,将子问题逐个解决(一般是同种方法),将已经解决的子问题合并,最后,算法会层层合并得到原问题的答案。
分治算法步骤:
分:递归地将问题分解为各个的子问题(性质相同的,相互独立的子问题)。
治:将这些规模更小的子问题逐个击破。
合:将已解决的问题逐层合并,最终得出原问题的解。
分治法适用条件
1、问题的规模缩小到一定的规模就可以较容易地解决。
2、问题可以分解为若干个规模较小的模式相同的子问题,即该问题具有最优子结构性质。
3、合并问题分解出的子问题的解可以得到问题的解。
4、问题所分解出的各个子问题之间是独立的,即子问题之间不存在公共的子问题。
❼ 点集的Delaunay三角剖分方法
3.2.1.1 基本理论
B.Delaunay于1934年提出了Delaunay三角网格的概念,它是Voronoi图(简称V图)的几何对偶图,具有严格的数学定义和完备的理论基础。
图3.1 Voronoi图(虚线)及对应的Delaunay三角剖分(实线)
3.2.1.1.1 Voronoi图
假设V={v1,v2,…,vN},N≥3是欧几里得平面上的一个点集,并且这些点不共线,四点不共圆。用d(vi,vj)表示点vi与vj间的欧几里得距离。
设x为平面上的点,则:
区域V(i)={x∈E2d(x,vi)≤d(x,vj),j=1,2,…,N,j≠i}称为Voronoi多边形,也称为该点的邻域。点集中所有点的Voronoi多边形组成Voronoi图,如图3.1所示。
平面上的Voronoi图可以看做是点集V中的每个点作为生长核,以相同的速率向外扩张,直到彼此相遇为止而在平面上形成的图形。除最外层的点形成开放的区域外,其余每个点都形成一个凸多边形。
3.2.1.1.2 Delaunay三角剖分
Delaunay三角形网格为V图的几何对偶图。在二维平面中,点集中若无四点共圆,则该点集V图中每个顶点恰好是3个边的公共顶点,并且是3个Voronoi多边形的公共顶点;上述3个Voronoi多边形所对应的点集中的点连成的三角形称为与该Voronoi顶点对应的Delaunay三角形,如图3.1所示。如果一个二维点集中有四点共圆的情况,此时,这些点对应的Voronoi多边形共用一个Voronoi顶点,这个公共的Voronoi顶点对应多于3个Voronoi多边形,也就是对应于点集中多于3个的点;这些点可以连成多于一个的三角形。此时,可以任意将上述几个点形成的凸包划分为若干三角形,这些三角形也称为和这个Voronoi顶点对应的Delaunay三角形。
所有与Voronoi顶点对应的Delaunay三角形就构成了Delaunay三角剖分。当无退化情况(四点共圆)出现时,点集的Delaunay三角剖分是唯一的。
3.2.1.1.3 Delaunay三角剖分的特性
Delaunay三角剖分具有两个重要特性:
(1)最小角最大化特性:即要求三角形的最小内角尽量最大,具体地说是指在两个相邻的三角形构成凸四边形的对角线,在相互交换后,6个内角的最小角不再增大,并且使三角形尽量接近等边。
(2)空外接圆特性:即三角形的外接圆中不包含其他三角形的顶点(任意四点不能共圆),该特性保证了最邻近的点构成三角形,使三角形的边长之和尽量最小。
3.2.1.2 常用算法
Delaunay三角剖分方法是目前最流行的通用的全自动网格生成方法之一。比较有效的Delaunay三角剖分算法有分治算法、逐点插入法和三角网生长法等(Tsai,1993),其中逐点插入法由于其算法的简洁性且易于实现,因而获得广泛的应用。其主要思路是先构建一个包含点集或区域的初始网格,再依次向初始网格中插入点,最后形成Delaunay三角剖分。
采用逐点插入法建立Delaunay三角网的算法思想最初是由Lawson于1977年提出的(Lawson,1977),Bowyer和Watson等先后对该算法进行了发展和完善(Bowyer,1981;Watson,1981)。目前涌现出的大量逐点插入法中,主要为以Lawson算法代表的对角线交换算法和以Bowyer-Watson算法代表的空外接圆法。
3.2.1.2.1 Lawson算法
Lawson算法的主要思想是将要插入的数据点逐一插入到一个已存在的Delaunay三角网内,然后再用局部优化算法(Local Optimization Procere,LOP)优化使其满足Delau-nay三角网的要求,其主要步骤如下:
图3.7 Bowyer-Watson算法剖分实例
❽ 《算法导论》(第三版)目录
1.1 算法
1.2 作为一种技术的算法
2.1 插入排序
2.2 分析算法
2.3 设计算法
2.3.1 分治法
2.3.2 分析分治算法
3.1 渐近记号
3.2 标准记号与常用函数
4.1 最大子数组问题
4.2 矩阵乘法的 Strassen 算法
4.3 用代入法求解递归式
4.4 用递归树方法求解递归式
4.5 用主方法求解递归式
*4.6 证明主定理
4.6.1 对 b 的幂证明主定理
4.6.2 向下取整和向上取整
5.1 雇佣问题
5.2 指示器随机变量
5.3 随机算法
*5.4 概率分析和指示器随机变量的进一步使用
5.4.1 生日悖论
5.4.2 球与箱子
5.4.3 特征序列
5.4.4 在线雇佣问题
6.1 堆
6.2 维护堆的性质
6.3 建堆
6.4 堆排序算法
6.5 优先队列
7.1 快速排序的描述
7.2 快速排序的性能
7.3 快速排序的随机化版本
7.4 快速排序分析
7.4.1 最坏情况分析
7.4.2 期望运行时间
8.1 排序算法的下界
8.2 计数排序
8.3 基数排序
8.4 桶排序
9.1 最小值和最大值
9.2 期望为线性时间的选择算法
9.3 最坏情况为线性时间的选择算法
10.1 栈和队列
10.2 链表
10.3 指针和对象的实现
10.4 有根树的表示
11.1 直接寻址表
11.2 散列表
11.3 散列函数
11.3.1 除法散列法
11.3.2 乘法散列法
*11.3.3 全域散列法
11.4 开放寻址法
11.5 完全散列
12.1 什么是二叉树
12.2 查询二叉搜索树
12.3 插入和删除
12.4 随机构建二叉搜索树
13.1 红黑树的性质
13.2 旋转
13.3 插入
13.4 删除
14.1 动态顺序统计
14.2 如何扩张数据结构
14.3 区间树
15.1 钢条切割
15.2 矩阵链乘法
15.3 动态规划原理
15.4 最长公共子序列
15.5 最优二叉搜索树
16.1 活动选择问题
16.2 贪心算法原理
16.3 赫夫曼编码
*16.4 拟阵和贪心算法
*16.5 用拟阵求解任务调度问题
17.1 聚合分析
17.2 核算法
17.3 势能法
17.4 动态表
17.4.1 表扩张
17.4.2 表扩张和收缩
18.1 B 树的定义
18.2 B 树上的基本操作
18.3 从 B 树上删除关键字
19.1 斐波那契结构
19.2 可合并堆操作
19.3 关键字减值和删除一个结点
19.4 最大度数的界
20.1 基本方法
20.2 递归结构
20.2.1 原型 van Emde Boas 结构
20.2.2 原型 van Emde Boas 结构上的操作
20.3 van Emde Boas 树及其操作
20.3.1 van Emde Boas 树
20.3.2 van Emde Boas 树的操作
21.1 不相交集合的操作
21.2 不相交集合的链表表示
21.3 不相交集合森林
*21.4 带路径压缩的按秩合并的分析
22.1 图的表示
22.2 广度优先搜索
22.3 深度优先搜索
22.4 拓扑排序
22.5 强连通分量
23.1 最小生成树的形成
23.2 Kruskal 算法和 Prim 算法
24.1 Bellman-Ford 算法
24.2 有向无环图中的单源最短路径问题
24.3 Dijkstra 算法
24.4 差分约束和最短路径
24.5 最短路径性质的证明
25.1 最短路径和矩阵乘法
25.2 Floyd-Warshall 算法
25.3 用于稀疏图的 Johnson 算法
26.1 流网络
26.2 Ford-Fulkerson 方法
26.3 最大二分匹配
*26.4 推送-重贴标签算法
*26.5 前置重贴标签算法
27.1 动态多线程基础
27.2 多线程矩阵乘法
27.3 多线程归并排序
28.1 求解线性方程组
28.2 矩阵求逆
28.3 对称正定矩阵和最小二乘逼近
29.1 标准型和松弛型
29.2 将问题表达为线性规划
29.3 单纯形算法
29.4 对偶性
29.5 初始基本可行解
30.1 多项式的表示
30.2 DFT 和 FFT
30.3 高效 FFT 实现
31.1 基础数论概念
31.2 最大公约数
31.3 模运算
31.4 求解模线性方程
31.5 中国余数定理
31.6 元素的幂
31.7 RSA 公钥加密系统
*31.8 素数的测试
*31.9 整数的因子分解
32.1 朴素字符串匹配算法
32.2 Rabin-Karp 算法
32.3 利用有限自动机进行字符串匹配
32.4 Knuth-Morris-Pratt 算法
33.1 线段的性质
33.2 确定任意一对线段是否相交
33.3 寻找凸包
33.4 寻找最近点对
34.1 多项式时间
34.2 多项式时间的验证
34.3 NP 完全性与可归约性
34.4 NP 完全性的证明
34.5 NP 完全问题
34.5.1 团问题
34.5.2 顶点覆盖问题
34.5.3 哈密顿回路问题
34.5.4 旅行商问题
34.5.5 子集和问题
35.1 顶点覆盖问题
35.2 旅行商问题
35.2.1 满足三角不等式的旅行商问题
35.2.2 一般旅行商问题
35.3 集合覆盖问题
35.4 随机化和线性规划
35.5 子集和问题
A.1 求和公式及其性质
A.2 确定求和时间的界
B.1 集合
B.2 关系
B.3 函数
B.4 图
B.5 树
B.5.1 自由树
B.5.2 有根树和有序树
B.5.3 二叉树和位置树
C.1 计数
C.2 概率
C.3 离散随机变量
C.4 几何分布与二项分布
C.5 二项分布的尾部
D.1 矩阵与矩阵运算
D.2 矩阵的基本性质
❾ 分治算法是什么呢
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。
解题步骤
分治法解题的一般步骤:
(1)分解,将要解决的问题划分成若干规模较小的同类问题;
(2)求解,当子问题划分得足够小时,用较简单的方法解决;
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
❿ 一、分治法
分治算法的主要思想是将原问题递归地分成若干个子问题,直到子问题满足边界条件,停止递归。将子问题逐个击破(一般是同种方法),将已经解决的子问题合并,最后,算法会层层合并得到原问题的答案。
使用分治算法其中一个要求是,子问题合并的代价不能太大,否则就起不了降低时间复杂度的效果了。
如果用传统的遍历法,时间复杂度过大,若使用分治法,则时间复杂度大大降低。