⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dijkstrasearch.cpp

📁 Dijkstra算法及demo实现
💻 CPP
字号:
#include "StdAfx.h"
#include "DijkstraSearch.h"

// 计算两点之间的距离(米)
#define DEG2RAD(X) (X / 57.2957795131)

double DegreesToMeters(double x1, double y1, double x2, double y2)
{
   if(x1==x2 && y1==y2) return 0.0;

   double a;//Use GRS 80 spheroid
   double f;//1 / 298.257
   a = 6378137.0;
   f = 0.003352813;

   double F1,G,l;
   F1 = (DEG2RAD(y1) + DEG2RAD(y2)) / 2.0;
   G = (DEG2RAD(y1) - DEG2RAD(y2)) / 2.0;
   l = (DEG2RAD(x1) - DEG2RAD(x2)) / 2.0;

   double sF2,cF2,sG2,cG2,sL2,cL2;
   sF2 = sin(F1) * sin(F1);
   cF2 = cos(F1) * cos(F1);
   sG2 = sin(G) * sin(G);
   cG2 = cos(G) * cos(G);
   sL2 = sin(l) * sin(l);
   cL2 = cos(l) * cos(l);

   double S,C;
   S = sG2 * cL2 + cF2 * sL2;
   C = cG2 * cL2 + sF2 * sL2;
	
   double omega,rho;
   omega = atan(sqrt(S / C));
   rho = sqrt(S * C) / omega;

   double d;
   d = 2 * a * omega;
	
   double H1,H2;
   H1 = (3 * rho - 1) / (2 * C);
   H2 = (3 * rho + 1) / (2 * S);

   double m;
   m = d * (1 + f * (H1 * sF2 * cG2 - H2 * cF2 * sG2));

   return (m * 0.0006214 * 1609);//乘1609将英里转换成米
}
/////////////////////////////////////////////////////////////////////////////////////////////

CDijkstraSearch::CDijkstraSearch(void)
{
	m_pMemObjectList=NULL;
	m_nObjectCount=0;
}

CDijkstraSearch::~CDijkstraSearch(void)
{
}

bool CDijkstraSearch::ConnectObject(MemSearchObject *pFirst,MemSearchObject *pSecond,bool bBoth)
{
	if(pFirst==NULL || pSecond==NULL) return false;
	pFirst->m_pNextMemObjectList.PushNode(pSecond);
	if(bBoth)
		pSecond->m_pNextMemObjectList.PushNode(pFirst);
	return true;
}

bool CDijkstraSearch::InitSearch(MemSearchObject *pMemObjectList,long nObjectCount)
{
	if(pMemObjectList==NULL || nObjectCount<=0) return false;
	m_pMemObjectList=pMemObjectList;
	m_nObjectCount=nObjectCount;
	return true;
}

bool CDijkstraSearch::StartSearch(MemSearchObject *pBeginObject,MemSearchObject *pEndObject,int nType,SearchObjectList *pSearchResult)
{
	if(pBeginObject==NULL || pEndObject==NULL || pSearchResult==NULL)
		return false;

	if(m_pMemObjectList==NULL || m_nObjectCount<=0) 
		return false;

	MemSearchResultList pMemResultList;//已搜索完成的路径列表
	long nFirstResultIndex=0;//已搜索结果pMemResultList中第一个有剩余邻结点的序号
	ValueType vNoUseValue,vMemValue; 
	
	//临时变量
	MemSearchObjectList *pMemSearchObjectList=NULL;
	MemSearchObject     *pMemSearchObject=NULL;
	register long i,j;
	long nCount=0;
	long jj,nCount2;

	//将所有的结点加入到没有参与搜索的结点
	for(i=0;i<m_nObjectCount;i++)
	{
		m_pMemObjectList[i].m_pLeftNextMemObjectList.RemoveAllNode();
		long n=m_pMemObjectList[i].m_pNextMemObjectList.GetNodeCount();
		for(long m=0;m<n;m++)
		{
			m_pMemObjectList[i].m_pLeftNextMemObjectList.PushNode(m_pMemObjectList[i].m_pNextMemObjectList.GetNode(m));
		}
	}

	//开始搜索
	while(1)
	{
		//从未使用的结点中,找出最短的 pNoUseLessObject
		MemSearchObject *pMemNoUseLessObject=NULL;
		vNoUseValue=OBJECT_MAXVALUE;
		if(pBeginObject->m_pLeftNextMemObjectList.GetNodeCount()>0)//如果首结点还有未使用的相邻结点
		{
			pMemSearchObjectList=&pBeginObject->m_pLeftNextMemObjectList;
			nCount=pMemSearchObjectList->GetNodeCount();
			for(j=0;j<nCount;j++)
			{
				pMemSearchObject=pMemSearchObjectList->GetNode(j);
				ValueType vTmp=pMemSearchObject->m_OwnerObject.GetValue(pBeginObject->m_OwnerObject,nType);
				if(vTmp<vNoUseValue)
				{	
					vNoUseValue=vTmp;
					pMemNoUseLessObject=pMemSearchObject;
				}
			}
		}

		//从已搜索完成的列表中,找出最短的 pMemLessObject
		MemSearchObject *pMemLessObject=NULL;
		vMemValue=OBJECT_MAXVALUE;
		
		//遍历pMemResultList
		MemSearchResult *pMemResult=NULL;
		MemSearchResult *pParentMemSearchObject=NULL;
		nCount=pMemResultList.GetNodeCount();

		//从有剩余邻结结点的结果查找,nFirstResultIndex表示可能有邻结结点的起始位置
		for(j=nFirstResultIndex;j<nCount;j++)
		{
			pMemResult=pMemResultList.GetNode(j);
			if(pMemResult->m_pMemObject->m_pLeftNextMemObjectList.GetNodeCount()<=0) 
			{
				if(j==nFirstResultIndex+1) nFirstResultIndex=j;
				continue;
			}

			//遍历每个最短路线,找下一结点最短路线
			pMemSearchObjectList=&pMemResult->m_pMemObject->m_pLeftNextMemObjectList;
			nCount2=pMemSearchObjectList->GetNodeCount();

			for(jj=0;jj<nCount2;jj++)
			{
				pMemSearchObject=pMemSearchObjectList->GetNode(jj);
				pMemResult->m_pMemObject->m_OwnerObject;
				ValueType vTmp=pMemSearchObject->m_OwnerObject.GetValue(pMemResult->m_pMemObject->m_OwnerObject,nType);
				vTmp+=pMemResult->m_vValue;

				if(vTmp<vMemValue)
				{
					vMemValue=vTmp;
					pParentMemSearchObject=pMemResult;
					pMemLessObject=pMemSearchObject;
				}
			}
		}

		//如果没有了可用的结点,就退出
		if(vNoUseValue==OBJECT_MAXVALUE && vMemValue==OBJECT_MAXVALUE)
			break;

		//加入到pMemResultList
		if(vNoUseValue<vMemValue)
		{
			//加了新的搜索结果
			MemSearchResult *pMemResult=new MemSearchResult;
			pMemResult->m_pParent=NULL;
			pMemResult->m_pMemObject=pMemNoUseLessObject;
			pMemResult->m_vValue=vNoUseValue;
			pMemResultList.PushNode(pMemResult);
			//移除一个已经使用的相邻结点,取消两相关的相邻关系
			pBeginObject->m_pLeftNextMemObjectList.RemoveNode(pMemNoUseLessObject);
			pMemNoUseLessObject->m_pLeftNextMemObjectList.RemoveNode(pBeginObject);

			if(pMemNoUseLessObject==pEndObject) break;//如果找到了就退出
		}
		else
		{
			//加了新的搜索结果
			MemSearchResult *pMemResult=new MemSearchResult;
			pMemResult->m_pParent=pParentMemSearchObject;
			pMemResult->m_vValue=vMemValue;
			pMemResult->m_pMemObject=pMemLessObject;
			pMemResultList.PushNode(pMemResult);
			//移除一个已经使用的相邻结点,取消两相关的相邻关系
			pParentMemSearchObject->m_pMemObject->m_pLeftNextMemObjectList.RemoveNode(pMemLessObject);
			pMemLessObject->m_pLeftNextMemObjectList.RemoveNode(pParentMemSearchObject->m_pMemObject);

			if(pMemLessObject==pEndObject) break;//如果找到了就退出
		}
	}

	//从pMemResultList查找到真正目标的线路,并保存到pSearchResult
	nCount=pMemResultList.GetNodeCount();
	MemSearchResult *pMemResult=NULL;

	for(j=0;j<nCount;j++)
	{
		pMemResult=pMemResultList.GetNode(j);
		//从pMemResult中查找pEndObject
		MemSearchResult *pMemSearchTmp=NULL;
		pMemSearchTmp=pMemResult;
		while(pMemSearchTmp!=NULL)
		{
			if(pMemSearchTmp->m_pMemObject->m_OwnerObject==pEndObject->m_OwnerObject)//找到了
			{
				//开始保存真正的结果到pSearchResult
				MemSearchResult *pMemSearchTmp2=pMemResult;
				while(pMemSearchTmp2!=NULL)
				{
					SearchObject *p=new SearchObject;
					*p=pMemSearchTmp2->m_pMemObject->m_OwnerObject;
					pSearchResult->PushNode(p);
					pMemSearchTmp2=pMemSearchTmp2->m_pParent;
				}
				//增加起始结点
				SearchObject *p=new SearchObject;
				*p=pBeginObject->m_OwnerObject;
				pSearchResult->PushNode(p);
				j=nCount;
				pSearchResult->ReserveNode();//将结点反序,使它从起点到终点顺序
				break;
			}
			
			pMemSearchTmp=pMemSearchTmp->m_pParent;
		}
	}

	//释放pMemResultList空间
	nCount=pMemResultList.GetNodeCount();
	for(j=0;j<nCount;j++)
	{
		pMemResult=pMemResultList.GetNode(j);
		delete pMemResult;
	}

	//释放临时的m_pLeftNextMemObjectList空间
	for(i=0;i<m_nObjectCount;i++)
	{
		m_pMemObjectList[i].m_pLeftNextMemObjectList.RemoveAllNode();
	}

	return (pSearchResult->GetNodeCount()>0)?true:false;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -