随机增量法较为简单,遵循增量法的一贯思路,即按照随机的顺序依次插入点集中的点,在整个过程中都要 维护并更新一个与当前点集对应的Delaunay三角剖分。考虑插入vi点的情况,由于前面插入所有的点v1,v2,...,vi-1构成的DT(v1, v2,...,vi-1)已经是Delaunay三角剖分,只需要考虑插入vi点后引起的变化,并作调整使得DT(v1,v2,...,vi-1) U vi成为新的Delaunay三角剖分DT(v1,v2,...,vi)。(插入调整过程:首先确定vi落在哪个三角形中(或边上),然后将vi与三角形三个顶点连接起来构成三个三角形(或与共边的两个三角形的对顶点连接起来构 成四个三角形),由于新生成的边以及原来的边可能不是或不再是Delaunay边,故进行边翻转来调整使之都成为Delaunay边,从而得出DT (v1,v2,...,vi)。)其Pseudocode如下:Algorithm IncrementalDelaunay(V)Input: 由n个点组成的二维点集VOutput: Delaunay三角剖分 a appropriate triangle boudingbox to contain V ( such as: we can use triangle abc, a=(0, 3M), b=(-3M,-3M), c=(3M, 0), M=Max({|x1|,|x2|,|x3|,...} U {|y1|,|y2|,|y3|,...})) DT(a,b,c) as triangle i <- 1 to n do (Insert(DT(a,b,c,v1,v2,...,vi-1), vi)) the boundingbox and relative triangle which cotains any vertex of triangle abc from DT(a,b,c,v1,v2,...,vn) and return DT(v1,v2,...,vn).Algorithm Insert(DT(a,b,c,v1,v2,...,vi-1), vi) the triangle vavbvc which contains vi // FindTriangle() (vi located at the interior of vavbvc) 3. then add triangle vavbvi, vbvcvi and vcvavi into DT // UpdateDT() FlipTest(DT, va, vb, vi) FlipTest(DT, vb, vc, vi) FlipTest(DT, vc, va, vi) if (vi located at one edge (. edge vavb) of vavbvc) 5. then add triangle vavivc, vivbvc, vavdvi and vivdvb into DT (here, d is the third vertex of triangle which contains edge vavb) // UpdateDT() FlipTest(DT, va, vd, vi) FlipTest(DT, vc, va, vi) FlipTest(DT, vd, vb, vi) FlipTest(DT, vb, vc, vi) DT(a,b,c,v1,v2,...,vi) Algorithm FlipTest(DT(a,b,c,v1,v2,...,vi), va, vb, vi) the third vertex (vd) of triangle which contains edge vavb // FindThirdVertex()(vi is in circumcircle of abd) // InCircle()3. then remove edge vavb, add new edge vivd into DT // UpdateDT() FlipTest(DT, va, vd, vi) FlipTest(DT, vd, vb, vi)复杂度分析问题的规模为点集中的点的总个数n(没有重合的点),循环内的基本的操作有:1.寻找插入点所在的三角形(FindTriangle())2.测试点是否在外接圆内(InCircle())3.更新三角网(UpdateDT())4.寻找共测试边的第三顶点(FindThirdVertex())考虑最坏情况:时间复杂度T = T(addboudingbox()) + Sum(T(insert(i), i=1,2,...,n)) + T(removeboundingbox)因为addboudingbox()和removeboundingbox不随n变化,是个常量。T(addboudingbox()) = O(1), T(removeboundingbox()) = O(1).T = Sum(T(insert(i), i=1,2,...,n)) + O(1) + O(1). 考虑插入第i个的点的时间: T(insert(i)) = T(FindTriangle(i)) + T(UpdateDT(i)) + K*T(FlipTest(i)) (K为常数)故T = Sum(T(FindTriangle(i)), i=1,2,..,n) + Sum(T(UpdateTD(i)), i=1,2,..,n) + K*Sum(T(FlipTest(i)), i=1,2,..,n)挨个考虑:FindTriangle(i)是要找出包含第i个点的三角形,由欧拉公式知道,平面图的面数F是O(n), n为顶点数,故此时总的三角形数是O(i)的。所以问题相当于在O(i)个记录中查找目标记录,如果不借助特殊的数据结构,按照一般顺序查找,需要O (i)的时间。T(FindTriangle(i)) = O(i),故:Sum(T(FindTriangle(i)), i=1,2,..,n) = O(n*n)UpdateTD(i)是更新三角网数据结构,插入和删除三角形到当前的三角网是个常量操作,因为已经知道插入和删除的位置。T(UpdateDT(i)) = O(1),故:Sum(T(UpdateTD(i)), i=1,2,..,n) = O(n)FlipTest(i)比较复杂些,是个递归过程。细分为:T(FlipTest(i)) = T(FindThirdVertex(i)) + T(InCircle(i)) + T(UpdateDT(i)) + 2*T(FlipTest(j))。(这里,用j来区分不同的深度)因为InCircle(i)是测试点是否在外接圆内,是个常量操作,不随点数变化而变化。故T(InCircle(i)) = O(1), 又T(UpdateDT(i) = O(1)(见上)FindThirdVertex(i)是查找目标点,在O(i)个记录中查找目标记录,如果不借助特殊的数据结构,按照一般顺序查找需要O(i)的时间。T(FindThirdVertex(i)) = O(i).剩下的是递归调用FlipTest的过程,不过还好,因为FlipTest的递归深度只有常数级(设为K)。正比于点在三角网中的度数(degree)。故FlipTest(i)最多调用的次数为2*2*,...,2 = K',还是常数。故T(FlipTest(i)) = O(i) + O(1) + O(1) + K'*(O(i) + O(1) + O(1)) = O(i) + O(1) + O(1) .Sum(T(FlipTest(i)), i=1,2,..,n) = O(n*n) + O(n) + O(n)综上,最坏情况下算法总时间复杂度 T = O(n*n) + O(n) + K*(O(n*n) + O(n) + O(n)) + O(1) + O(1) = O(n*n) 其中,关键的操作是FindTriangle()和FindThirdVertex(),都是n*n次的。在网上很多资料说随机增量法是O(nlogn)的,但是分析下来,却是O(n*n)的。后来看到别人的实 现,原来是用的别的数据结构来存储三角网,减少了FindTriangle()和FindThirdVertex()的复杂度。使得某次查找三角形和共边 三角形的第三顶点能在O(logn),而非O(n)的时间内实现。这样,总的查找的时间为 O(log1)+O(log2)+,...+O(logn) = O(nlogn)。程序=算法+数据结构,看来一点没错。比如说用DAG,Quad-edge等,都能达到O(nlogn)的复杂度。分治法(Divide and Conquer)据说是现在实际表现最好的。