点集中最短距离点对的距离
性质
求取输入点集最近点对的距离
相比于对所有点对穷举,并得出结果的方式相比,
本算法时间复杂度为Θ(nlg(n)),优于穷举下的Θ(n^2)
接口设计
extern "C" class ALGORITHMLIB MinDistance
{
public:
enum Flag
{
LEFT,
RIGHT,
};
class FlagPoint
{
public:
FlagPoint();
FlagPoint(Math::Point<2>* pPo_, Flag nFlag_);
~FlagPoint();
public:
Math::Point<2> m_poP;
Flag m_nFlag;
};
MinDistance();
~MinDistance();
double Run(const DataStruct::Array::DynArray>& poArr_);
private:
double CalculateMinDistance(
const DataStruct::Array::DynArray& arrPos_,
const DataStruct::Array::DynArray& arrSortedByX_,
const DataStruct::Array::DynArray& arrSortedByY_);
};
实现
内部类
MinDistance::FlagPoint::FlagPoint()
{
m_nFlag = Flag::LEFT;
}
MinDistance::FlagPoint::FlagPoint(Math::Point<2>* pPo_, Flag nFlag_)
{
m_nFlag = nFlag_;
}
MinDistance::FlagPoint::~FlagPoint()
{
}
构造
MinDistance::MinDistance()
{
}
析构
MinDistance::~MinDistance()
{
}
算法运行
double MinDistance::Run(const DataStruct::Array::DynArray>& arrPos_)
{
DataStruct::Array::DynArray _parrFPo;
int _nSize = arrPos_.GetSize();
for (int _i = 0; _i < _nSize; _i++)
{
FlagPoint* _pFPo = new FlagPoint();
_pFPo->m_poP = arrPos_[_i];
_parrFPo.Add(_pFPo);
}
DataStruct::Array::DynArray _parrFPosSortedByX = _parrFPo;
_parrFPosSortedByX.Sort(
[](const FlagPoint*& po1_, const FlagPoint*& po2_)
{
double _nRet = po1_->m_poP.m_nPos[0] - po2_->m_poP.m_nPos[0];
if (_nRet > 0.0)
{
return 1;
}
else if (_nRet < 0.0)
{
return -1;
}
else
{
return 0;
}
});
DataStruct::Array::DynArray _parrFPosSortedByY = _parrFPo;
_parrFPosSortedByY.Sort(
[](const FlagPoint*& po1_, const FlagPoint*& po2_)
{
double _nRet = po1_->m_poP.m_nPos[1] - po2_->m_poP.m_nPos[1];
if (_nRet > 0.0)
{
return 1;
}
else if (_nRet < 0.0)
{
return -1;
}
else
{
return 0;
}
});
double _nMin = CalculateMinDistance(
_parrFPo,
_parrFPosSortedByX,
_parrFPosSortedByY);
for (int _i = 0; _i < _nSize; _i++)
{
delete _parrFPo[_i];
_parrFPo[_i] = nullptr;
}
}
double MinDistance::CalculateMinDistance(
const DataStruct::Array::DynArray& parrFPos_,
const DataStruct::Array::DynArray& parrFPosSortedByX_,
const DataStruct::Array::DynArray& parrFPosSortedByY_)
{
double _nMinDistance = 0.0;
int _nSize = parrFPos_.GetSize();
if (_nSize <= 3)
{
_nMinDistance = Geometry::GetDistance(parrFPos_[0]->m_poP, parrFPos_[1]->m_poP);
for (int _i = 0; _i < _nSize; _i++)
{
for (int _j = 0; _j < _nSize; _j++)
{
if (_j == _i)
{
continue;
}
double _nD = Geometry::GetDistance(parrFPos_[_i]->m_poP, parrFPos_[_j]->m_poP);
if (_nMinDistance < _nD)
{
_nMinDistance = _nD;
}
}
}
return _nMinDistance;
}
// 对n个节点做类型划分
for (int _i = 0; _i < _nSize; _i++)
{
if (_i < _nSize / 2)
{
parrFPosSortedByX_[_i]->m_nFlag = Flag::LEFT;
}
else
{
parrFPosSortedByX_[_i]->m_nFlag = Flag::RIGHT;
}
}
// 划分为两个集合
DataStruct::Array::DynArray _parrPosLeft;
DataStruct::Array::DynArray _parrLeftSortedByX;
DataStruct::Array::DynArray _parrLeftSortedByY;
DataStruct::Array::DynArray _parrPosRight;
DataStruct::Array::DynArray _parrRightSortedByX;
DataStruct::Array::DynArray _parrRightSortedByY;
for (int _i = 0; _i < _nSize; _i++)
{
if (parrFPos_[_i]->m_nFlag == Flag::LEFT)
{
_parrPosLeft.Add(parrFPos_[_i]);
}
else
{
_parrPosRight.Add(parrFPos_[_i]);
}
if (parrFPosSortedByX_[_i]->m_nFlag == Flag::LEFT)
{
_parrLeftSortedByX.Add(parrFPosSortedByX_[_i]);
}
else
{
_parrRightSortedByX.Add(parrFPosSortedByX_[_i]);
}
if (parrFPosSortedByY_[_i]->m_nFlag == Flag::LEFT)
{
_parrLeftSortedByY.Add(parrFPosSortedByY_[_i]);
}
else
{
_parrRightSortedByY.Add(parrFPosSortedByY_[_i]);
}
}
double _nMinDLeft = CalculateMinDistance(_parrPosLeft, _parrLeftSortedByX, _parrLeftSortedByY);
double _nMinDRight = CalculateMinDistance(_parrPosRight, _parrRightSortedByX, _parrRightSortedByY);
double _nMin = std::fmin(_nMinDLeft, _nMinDRight);
DataStruct::Array::DynArray _parrMidAreaSortedByY;
double _nMiddleX = parrFPosSortedByX_[_nSize / 2]->m_poP.m_nPos[0];
for (int _i = 0; _i < _nSize; _i++)
{
if (parrFPosSortedByY_[_i]->m_poP.m_nPos[0] >= (_nMiddleX - _nMin)
&& parrFPosSortedByY_[_i]->m_poP.m_nPos[0] <= (_nMiddleX + _nMin))
{
_parrMidAreaSortedByY.Add(parrFPosSortedByY_[_i]);
}
}
int _nMiddleAreaSize = _parrMidAreaSortedByY.GetSize();
for (int _i = 0; _i < _nMiddleAreaSize; _i++)
{
int _nCount = 1;
while (_nCount <= 7 && (_i + _nCount) < _nMiddleAreaSize)
{
double _nD = Geometry::GetDistance(_parrMidAreaSortedByY[_i]->m_poP, _parrMidAreaSortedByY[_i + _nCount]->m_poP);
_nMin = std::fmin(_nMin, _nD);
_nCount++;
}
}
return _nMin;
}
算法目标&正确性证明
算法思想:
算法:求取输入点集A最小距离
若点集A中,点的个数小于或等于3,直接给出结果。
对点集A一分为二,AL,AR
对AL,AR分别用算法求取AL,AR最小距离d_al,d_ar
令d = min(d_al, d_ar)
处理,最小距离两点一个位于AL,一个位于AR的情形
构造以中线两边距离中线距离为d或不足d的点构成的点集P
对点集P中点按Y坐标排序
对点集P中每个点,依次与其后7个点比较。
如此,得到一个P中点的最小距离d_p
返回min(d, d_p)