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

📄 searchlib.cpp

📁 在VC的环境下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "searchlib.h"

int VERTEXTYPE::operator < (const VERTEXTYPE & right)
{
	return ((g+h)<(right.g+right.h));
}

int VERTEXTYPE::operator == (const VERTEXTYPE & right)
{
	return (nIndex == right.nIndex);
}

void InsertNode(ALGRAPH * graph = NULL, const VERTEXTYPE * node = NULL, int nIndex = -1)
{

}

void InitNodes(ALGRAPH & graph)
{
	int i = 0;
	
	for(i=0; i<MAX_VERTEX_NUM; i++)
	{
		graph.vertices[i].data.nIndex = i;
	}
}

int CreateRandomGraph(ALGRAPH & graph)
{
	InitNodes(graph);

	SetCoordinates(graph);

	Link(graph);

	SetArcWeight(graph);

	return 1;	
}

int SetCoordinates(ALGRAPH & graph)
{
	int i = 0;
	int j = 0;

	// 赋随机x坐标值
	double nPrePointCoordinateX = 0.0;
	for(i=VERTEX_HEIGHT-1; i>=0; i--)
	{
		nPrePointCoordinateX = 0.0;
		for(j=0; j<VERTEX_WIDTH; j++)
		{
			graph.vertices[i*VERTEX_WIDTH+j].data.x = nPrePointCoordinateX + X_MARCH 
				+ Random() % RANDOM_X_SCALE;
			nPrePointCoordinateX = graph.vertices[i*VERTEX_WIDTH+j].data.x;
		}
	}

	// 赋随机y坐标值
	double nPrePointCoordinateY = 0.0;
	for(j=0; j<VERTEX_WIDTH; j++)
	{
		nPrePointCoordinateY = 0.0;
		for(i=VERTEX_HEIGHT-1; i>=0; i--)
		{
			graph.vertices[i*VERTEX_WIDTH+j].data.y = nPrePointCoordinateY + Y_MARCH 
				+ Random() % RANDOM_Y_SCALE;
			nPrePointCoordinateY = graph.vertices[i*VERTEX_WIDTH+j].data.y;
		}
	}

	return 1;
}

int Link(ALGRAPH & graph)
{
	int i = 0;
	int j = 0;

	// 连接上下左右节点
	int nTab[MAX_LINK_NUM] = {-VERTEX_WIDTH, VERTEX_WIDTH, -1, 1};
	int nAdjvex = 0;
	for(i=0; i<MAX_VERTEX_NUM; i++)
	{
		for(j=0; j<MAX_LINK_NUM; j++)
		{
			nAdjvex = i + nTab[j];
			if(nAdjvex>=0 && nAdjvex<MAX_VERTEX_NUM)
			{
				if(!((i+1)%VERTEX_WIDTH) && 3==j)
				{// 右边界节点无右邻接节点
					continue;
				}
				if(!(i%VERTEX_WIDTH) && 2==j)
				{// 左边界节点无左边界节点
					continue;
				}
				// 连接
				graph.vertices[i].ArcList.push_back(ARCNODE(nAdjvex, -1.0, VALIDATE_WEIGHT_DOWN_LIMIT-1.0));
			}
		}
	}

	graph.nVexNum = MAX_VERTEX_NUM;
	graph.nArcNum = (VERTEX_WIDTH - 1) * VERTEX_WIDTH
		+ (VERTEX_HEIGHT - 1) * VERTEX_HEIGHT;

	return 1;
}

int SetArcWeight(ALGRAPH & graph)
{
	int i = 0;
	int j = 0;

	// 连接上下左右的节点
	double dCurX = 0.0;
	double dCurY = 0.0;
	for(i=0; i<MAX_VERTEX_NUM; i++)
	{
		list<ARCNODE>::iterator iter = graph.vertices[i].ArcList.begin();
		for(; iter!=graph.vertices[i].ArcList.end(); iter++)
		{
			ARCNODE & arcNode = *iter;
			// 查询该弧的权值是否已经计算出来
			ARCNODE * pArcNode = NULL;
			if(pArcNode = FindArc(graph, arcNode.nAdjvex, i))
			{
				if(!(pArcNode->info.dDistance < VALIDATE_WEIGHT_DOWN_LIMIT))
				{
					arcNode.info.dDistance = pArcNode->info.dDistance;
					arcNode.info.dWeight = pArcNode->info.dWeight;
					continue;
				}
			}

			// 计算新的权值 
			dCurX = graph.vertices[arcNode.nAdjvex].data.x;
			dCurY = graph.vertices[arcNode.nAdjvex].data.y;
			arcNode.info.dDistance = sqrt((graph.vertices[i].data.x - dCurX) 
				* (graph.vertices[i].data.x - dCurX)
				+ (graph.vertices[i].data.y - dCurY)
				* (graph.vertices[i].data.y - dCurY)); // + rand() % WEIGHT_SCALE;
			arcNode.info.dWeight = arcNode.info.dDistance * 
				(1.2 + ((double)(20 - (Random() % WEIGHT_SCALE))) / 100.0);
		}

	}

	return 1;
}

ARCNODE * FindArc(ALGRAPH & graph, int nArcStart, int nArcEnd)
{
	if(nArcStart<0 || nArcStart>=MAX_VERTEX_NUM
		|| nArcEnd<0 || nArcEnd>=MAX_VERTEX_NUM)
	{
		return NULL;
	}

	list<ARCNODE>::iterator iterArc = 
		graph.vertices[nArcStart].ArcList.begin();
	for(; iterArc!=graph.vertices[nArcStart].ArcList.end(); iterArc++)
	{
		ARCNODE & arcNode = *iterArc;
		if(nArcEnd == arcNode.nAdjvex)
		{
			return &arcNode;
		}
	}

	return NULL;
}

int ShortestPath_AStart(ALGRAPH & graph, int ns, int ng, 
						list<int> & listShortestPath, STUDYRESULT & resultPath)
{
	resultPath.nNodeNumberOnASelectedPath = 0;
	resultPath.nNumberOfExpandedNode = 0;

	// 1.将开始节点ns放入OPEN表;
    // 2.如果OPEN表为空,返回错误,并退出;
    // 3.在OPEN队列中选择f(np)最小的节点np移出放入CLOSED表;
    // 4.如果np是终点ng,成功退出,并通过回溯指针返回最短路径;
    // 5.否则,扩展节点np周围所有的节点ni,并给每个节点赋上指向父节点   
    //   的指针。
    // 5a.如果ni不在OPEN或CLOSED表里,估计h(ni),并计算
	//    f(ni)=g(ni)+h(ni), g(ni)=g(np)+c(np, ni), g(ns)=0,并放入OPEN表;
	// 5b.如果ni已经在OPEN或CLOSED表里,使它的回溯指针指向g(ni)值最小的路  
	//    径。(这一点保证当前节点ni回溯指针所指的路径ns→np的路径代价最
	//    小)。
	// 5c.如果ni的回溯指针调整了且ni在CLOSED表中,则从CLOSED表中移出放入
    //    OPEN表中。
    // 6.返回第2步。

	// 初始化
	int nNodeNo = 0;
	for(nNodeNo=0; nNodeNo<graph.nVexNum; nNodeNo++)
	{
		graph.vertices[nNodeNo].data.h = -1.0;
		graph.vertices[nNodeNo].data.g = -1.0;
		graph.vertices[nNodeNo].data.nFatherIndex = -1;
	}

	// 定义所需的变量
	list<VERTEXTYPE> OPEN;
	list<VERTEXTYPE> CLOSED;
	double g = 0.0;

	// 1.将开始节点ns放入OPEN表;
	graph.vertices[ns].data.g = 0.0;
	OPEN.push_back(graph.vertices[ns].data);

	// 2.如果OPEN表为空,返回错误,并退出;
	while (!OPEN.empty())
	{
		// 对OPEN排序
		OPEN.sort();

		// 3.在OPEN队列中选择f(np)最小的节点np移出放入CLOSED表;
		VERTEXTYPE np = *OPEN.begin();
		CLOSED.push_back(np);
		OPEN.pop_front();

		// 4.如果np是终点ng,成功退出,并通过回溯指针返回最短路径;
		if(np.nIndex == ng)
		{
			// 记录最短路径长度
			resultPath.dCostSumOnASelectedPath = np.g;

			// 设置最短路径
			listShortestPath.push_front(np.nIndex);
			while(np.nFatherIndex >= 0)
			{
				listShortestPath.push_front(np.nFatherIndex);
				np = graph.vertices[np.nFatherIndex].data;
			}
			
			// 记录最短路径长度
			resultPath.nNodeNumberOnASelectedPath = (int) listShortestPath.size();

			// 返回成功
			return 1;
		}

		// 5.否则,扩展节点np周围所有的节点ni,并给每个节点赋上指向父节点的回溯指针。   
		list<ARCNODE>::iterator iterNi = graph.vertices[np.nIndex].ArcList.begin();
		for(; iterNi!=graph.vertices[np.nIndex].ArcList.end(); iterNi++)
		{
			ARCNODE & ni = *iterNi;

			// 节点ni是np的父节点,不处理
			if(ni.nAdjvex == np.nFatherIndex)
			{
				continue;
			}

			// 记录扩展的节点数
			resultPath.nNumberOfExpandedNode++;
			
			// 在OPEN表和CLOSED表中查找ni
			list<VERTEXTYPE>::iterator iterOpenFind = OPEN.begin();
			int nOpenFound = 0;
			for(; iterOpenFind!=OPEN.end(); iterOpenFind++)
			{
				VERTEXTYPE & node = *iterOpenFind;
				if(node.nIndex == graph.vertices[ni.nAdjvex].data.nIndex)
				{
					nOpenFound = 1;

⌨️ 快捷键说明

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