分治法-04最近点对

——借鉴有利有弊。

 

http://blog.csdn.net/midgard/article/details/4199043 此博文介较为详细。

 

问题:点对集合 ptList[n] 求最近两点。

 

1.排序,以点坐标的X坐标从小到大排序。

 

以下递归求解。

 

1.如果点数<2,返回int.maxvalue。如果是2,3 即<4,则采用蛮力法直接计算。因为2个点直接可计算距离返回,如果是3个点采用分治划分的话,一侧没有或者有1个点,则无法计算,所以在点数是2或者3的时候直接计算出距离或者最小距离返回。

2.以集合索引的中间项ptList[mid]作为参考标准,<ptList[mid].X 的为左侧,>ptList[mid].X的为右侧。

3.分别求出左侧距离leftMid,右侧距离RightMid。对比求出当前最小距离currentDis = ?

4.此时的currentDis并不一定是最小的距离,因为最小距离的两个点可能分布在中轴两侧,故需要以中轴点p.X左右各取currentDis的长度,在此两侧范围内的点再采用蛮力计算方法计算出中轴范围内最短距离midDis.

image   image

5.对比currentDis和midDis,获取该数据规模范围内的最短距离并返回。

 

//分治递归求点对距离
private int PointRescuverAnalysis(List<Point> pts, int leftIndex, int rightIndex, PointPairIndex minPtPair)
{
if ((rightIndex-leftIndex+1) < 2)
{
//throw new Exception("需要至少2个点");
return int.MaxValue;
}

if ((rightIndex - leftIndex + 1) < 4)
{
return PointSequenceAnalysis(pts, leftIndex, rightIndex, minPtPair);
}

int midIndex = (leftIndex + rightIndex) / 2;
PointPairIndex leftPairIndex = new PointPairIndex();
int leftDis = PointRescuverAnalysis(pts, leftIndex, midIndex, leftPairIndex);
PointPairIndex rightPairIndex = new PointPairIndex();
int rightDis = PointRescuverAnalysis(pts, midIndex + 1, rightIndex, rightPairIndex);

int currentMinDis = int.MaxValue;
//当前最小距离
if (leftDis < rightDis)
{
minPtPair.LeftIndex = leftPairIndex.LeftIndex;
minPtPair.RightIndex = leftPairIndex.RightIndex;
currentMinDis = leftDis;
}
else
{
minPtPair.LeftIndex = rightPairIndex.LeftIndex;
minPtPair.RightIndex = rightPairIndex.RightIndex;
currentMinDis = rightDis;
}

//求中间最小距离
int stripLeft = leftIndex;
int stripRight = rightIndex;

for (int i = leftIndex; i < midIndex; i++)
{
if ((pts[midIndex].X - pts[i].X) < currentMinDis)
{
stripLeft = i;
break;
}
}

for (int i = rightIndex; i > midIndex; i--)
{
if ((pts[i].X-pts[midIndex].X) < currentMinDis)
{
stripRight = i;
break;
}
}

PointPairIndex midPair = new PointPairIndex();
int midDis = PointSequenceAnalysis(pts, stripLeft, stripRight, midPair);

if (currentMinDis > midDis)
{
currentMinDis = midDis;
minPtPair.LeftIndex = midPair.LeftIndex;
minPtPair.RightIndex = midPair.RightIndex;
}

return currentMinDis;
}

//蛮力求点对距离,返回最短距离平方
private int PointSequenceAnalysis(List<Point> pts,int leftIndex,int rightIndex,PointPairIndex pairIndex)
{
int minDis = int.MaxValue;
for (int i = leftIndex; i <= rightIndex; i++)
{
for (int j = i + 1; j <= rightIndex; j++)
{
int tempDis = ComputeDistance(pts[i], pts[j]);
if (tempDis < minDis)
{
minDis = tempDis;
pairIndex.LeftIndex = i;
pairIndex.RightIndex = j;
}
}
}

return minDis;
}

private int ComputeDistance(Point ptLeft, Point ptRight)
{
return (ptLeft.X - ptRight.X) * (ptLeft.X - ptRight.X) + (ptLeft.Y - ptRight.Y) * (ptLeft.Y - ptRight.Y);
}

imageimage

 

不过数据量大的话,运算还是有些慢的。

你可能感兴趣的:(分治法)