使用最笨的方法實現,遞歸遍歷的方式,有待持續的優化。附件中有原始代碼和測試用例。
#include "commondef.h" #include "depthsearch.h" #ifdef __cplusplus extern "C" { #endif void SearchDestNode ( const MapEdge *pstEdgeList, UINT32 ulEdgeCnt, NodeName *pstNodeList, UINT32 ulDepth, NodeDistance preDistance, const NodeName *pNodeTo, NodeDistance *pMinDistance ) { UINT32 ulLoop; const MapEdge *pstEdge; NodeName *pTempNodeName; UINT32 isFromAdd; UINT32 isToAdd; /* 如果上一層處理的最後節點,是結束節點,立即返回 */ if (pstNodeList[ulDepth - 1] == *pNodeTo) { if (preDistance < *pMinDistance) { *pMinDistance = preDistance; } return; } for (ulLoop = 0; ulLoop < ulEdgeCnt; ulLoop++) { pstEdge = pstEdgeList + ulLoop; /* 已經結束,立即返回 */ if ((pstEdge->nodeFrom == *pNodeTo && pstNodeList[ulDepth - 1] == pstEdge->nodeTo) || (pstEdge->nodeTo == *pNodeTo && pstNodeList[ulDepth - 1] == pstEdge->nodeFrom)) { if (preDistance + pstEdge->nodeDistance < *pMinDistance) { *pMinDistance = preDistance + pstEdge->nodeDistance; } return; } /* 當前節點起始位置都在路徑中存在,跳過此節點 */ pTempNodeName = pstNodeList; isFromAdd = BOOL_FALSE; isToAdd = BOOL_FALSE; while (pTempNodeName < pstNodeList + ulDepth) { if (*pTempNodeName == pstEdge->nodeFrom) { isFromAdd = BOOL_TRUE; } if (*pTempNodeName == pstEdge->nodeTo) { isToAdd = BOOL_TRUE; } pTempNodeName++; } /* 當銜接上一層節點,並且下一個節點不在鏈表中,繼續拼接 */ if (isFromAdd ^ isToAdd) { if (pstNodeList[ulDepth - 1] == pstEdge->nodeFrom && !isToAdd) { pstNodeList[ulDepth] = pstEdge->nodeTo; SearchDestNode(pstEdgeList, ulEdgeCnt, pstNodeList, ulDepth + 1, preDistance + pstEdge->nodeDistance, pNodeTo, pMinDistance); } else if (pstNodeList[ulDepth - 1] == pstEdge->nodeTo && !isFromAdd) { pstNodeList[ulDepth] = pstEdge->nodeFrom; SearchDestNode(pstEdgeList, ulEdgeCnt, pstNodeList, ulDepth + 1, preDistance + pstEdge->nodeDistance, pNodeTo, pMinDistance); } } } } NodeDistance ApiCalMinDistance ( const MapEdge *pstEdgeList, UINT32 ulEdgeCnt, const NodeName *pNodeFrom, const NodeName *pNodeTo, const SysCallBackFun *pstCallback ) { NodeName *ptNodeList; NodeDistance minDistance = MAX_DISTANCE; UINT32 ulLoop; ptNodeList = (NodeName *)pstCallback->pfMemAlloc(sizeof(NodeName) * ( 2 * ulEdgeCnt - 1)); if (ptNodeList == NULL_PTR) { return minDistance; } if (*pNodeFrom == *pNodeTo) { for (ulLoop = 0; ulLoop < ulEdgeCnt; ulLoop++) { if ((pstEdgeList[ulLoop].nodeFrom == *pNodeFrom) || (pstEdgeList[ulLoop].nodeTo == *pNodeFrom)) { return MIN_DISTANCE; } } } else { for (ulLoop = 0; ulLoop < ulEdgeCnt; ulLoop++) { if (pstEdgeList[ulLoop].nodeFrom == *pNodeFrom) { ptNodeList[0] = *pNodeFrom; ptNodeList[1] = pstEdgeList[ulLoop].nodeTo; SearchDestNode(pstEdgeList, ulEdgeCnt, ptNodeList, 2, pstEdgeList[ulLoop].nodeDistance, pNodeTo, &minDistance); } else if (pstEdgeList[ulLoop].nodeTo == *pNodeFrom) { ptNodeList[0] = *pNodeFrom; ptNodeList[1] = pstEdgeList[ulLoop].nodeFrom; SearchDestNode(pstEdgeList, ulEdgeCnt, ptNodeList, 2, pstEdgeList[ulLoop].nodeDistance, pNodeTo, &minDistance); } } } pstCallback->pfMemFree(ptNodeList); return minDistance; } #ifdef __cplusplus } #endif