Map Find Way

// NoDirectMapWay.cpp : 定义控制台应用程序的入口点。
/**
@coder:chaolee
@time:2014/12/06 11:30
@功能:无向图求简单路径
*/

#include "stdafx.h"

//常量定义:
#define MaxNode 20												//最大节点个数
#define InfoSize 10												//节点信息最大长度
#define FileName "D:\\map.dat"									//图原始信息的配置文件
#define bufferSize 30											//文件行缓冲区大小

/****************************************************************************************/

//自定义数据类型定义:

typedef char InfoType[InfoSize];								//节点信息类型


typedef struct Anode{
	int id;														//节点Id
	Anode * next;												//下一个边节点
}ArcNode;														//边节点定义


typedef struct Vnode{
	int id;														//节点Id
	//InfoType info;											//节点信息,在本例中未用到
	bool IsAvailable;											//该节点是否可走
	ArcNode * firstarc;											//第一个边节点
}VNode;															//头结点定义

typedef VNode AdjList[MaxNode];									//AdjList是邻接表类型

typedef struct wayinfo{
	int id;														//记录当前位置id
	ArcNode * p;												//记录当前节点下一个节点的指针
}WayInfo;

typedef struct{
	WayInfo stack[MaxNode];										//位置信息栈区
	int top;													//栈顶指针
}MapStack;

/*******************************************************************************************/

//自定义函数:

//求10的n次幂
int Pow10(int n)
{
	int result = 1;
	for (int i = 0; i < n; i++)
		result *= 10;
	return result;
}

//获取多位数 位移量pos自动变化
int GetNum(char *s,int &pos)
{
	char buff[5] = {0};											//数字缓冲区,最大支持5位数
	int i = 0,j=0,result=0;
	while (*(s + pos) >= '0'&&*(s + pos) <= '9'&&i<5){
		buff[i] = *(s + pos);
		i++; pos++;
	}
	i--;
	for (j = i; j >= 0; j--)
		result += (buff[j] - '0')*Pow10(i-j);
	return result;
}

//从文件中创建图 v为邻接表头结点数组指针
bool FiletoMap(VNode * v)
{
	char buffer[bufferSize] = {0};
	FILE *fp = NULL;
	int i=0,j=0;
	char ch;													
	ArcNode *temp = NULL;
	fopen_s(&fp,FileName,"rb");													//打开文件
	if (fp == NULL)
		return false;															//打开失败返回false
	while (!feof(fp)){															//循环读取文件行
		memset(buffer,0,bufferSize);
		fgets(buffer, 30, fp);
		j = 0;
		if (*buffer == ';'|| *buffer=='\0')
			continue;
		else{
			(v + i)->id = GetNum(buffer,j);										//头结点id赋值
			(v + i)->IsAvailable = true;										//将该头结点状态改为可以使用
			(v + i)->firstarc = NULL;
			for (j++; (ch=*(buffer + j)) != '\r' && ch!='\0'; j++){
				if (ch == ',')
					continue;
				else{
					temp = (ArcNode *)malloc(sizeof(ArcNode));					//分配边节点空间
					temp->id = GetNum(buffer,j);
					temp->next = (v+i)->firstarc;
					(v + i)->firstarc = temp;
					j--;
				}
			}
			i++;
		}
	}
	fclose(fp);																//关闭文件资源
	return true;
}

//判断某点是否可走
bool IsReachable(VNode * m,ArcNode * p)
{
	return (m + p->id)->IsAvailable;
}

//给出起点和终点在图中寻找所有路径(用栈实现)
bool FindWayfromMap(VNode * m,int start,int stop,int must=-1,int mustnot=-1)
{
	int wayCount = 0;														//路径计数
	int idTemp=0;
	char suffix[5] = {0};													//输出前缀缓冲区,最长为4个字节
	MapStack ms;															//定义路径栈
	ms.top = -1;															//栈初始化
	if (start >= MaxNode || (m + start)->IsAvailable == false){				//判断起点是否在图中
		printf("图中没有这个起点,你确定没有在逗我!");
		return false;
	}
	if (stop >= MaxNode || (m + stop)->IsAvailable == false){				//判断终点是否在图中
		printf("图中没有这个终点,你确定没有在逗我!");
		return false;
	}
	ms.stack[++ms.top].id = (m + start)->id;								//当前节点进栈
	ms.stack[ms.top].p = (m + ms.stack[ms.top].id)->firstarc;				//初始化当前节点的下一个
	(m + ms.stack[ms.top].id)->IsAvailable = false;							//将该点位置设置为不可走

	while (ms.top > -1){													//栈不空,循环
		if (ms.stack[ms.top].id == stop){									//找到一条路径
			if (must == -1 && mustnot == -1){
				printf("第%d条路径为:\t", ++wayCount);
				for (int i = 0; i <= ms.top; i++){								//输出找到的路径
					printf("%s  %d", suffix, ms.stack[i].id);
					strcpy_s(suffix, 3, "->");
				}
				printf("\n");
				memset(suffix, 0, 5);
			}
			else if (must != -1){
				bool mustMark=false;
				for (int i = 0; i <= ms.top; i++)
					if (ms.stack[i].id == must){
						mustMark = true;
						break;
					}
				if (mustMark == true){
					printf("第%d条路径为:\t", ++wayCount);
					for (int i = 0; i <= ms.top; i++){								//输出找到的路径
						printf("%s  %d", suffix, ms.stack[i].id);
						strcpy_s(suffix, 3, "->");
					}
					printf("\n");
					memset(suffix, 0, 5);											//恢复前缀为空
				}
			}								
			else if (mustnot != -1){
				bool mustnotMark = false;
				for (int i = 0; i <= ms.top; i++)
					if (ms.stack[i].id == mustnot){
						mustnotMark = true;
						break;
					}
				if (mustnotMark == false){
					printf("第%d条路径为:\t", ++wayCount);
					for (int i = 0; i <= ms.top; i++){								//输出找到的路径
						printf("%s  %d", suffix, ms.stack[i].id);
						strcpy_s(suffix, 3, "->");
					}
					printf("\n");
					memset(suffix, 0, 5);											//恢复前缀为空
				}
			}
			(m + ms.stack[ms.top].id)->IsAvailable = true;					//退栈
			ms.top--;
			if (ms.top>-1)
				ms.stack[ms.top].p = ms.stack[ms.top].p->next;				//将退栈后的栈顶元素的下一个处理元素后移
		}

		if (ms.stack[ms.top].p == NULL)	{									//该节点没有下一个节点,则继续退栈
			(m + ms.stack[ms.top].id)->IsAvailable = true;
			ms.top--;
			if (ms.top>-1)
				ms.stack[ms.top].p = ms.stack[ms.top].p->next;
		}
		else{
			if (IsReachable(m, ms.stack[ms.top].p)){						//下一个节点可走,进栈
				idTemp = ms.stack[ms.top].p->id;
				ms.stack[++ms.top].id = idTemp;
				ms.stack[ms.top].p = (m + idTemp)->firstarc;
				(m + idTemp)->IsAvailable = false;
			}
			else														   //下一个节点不可走,则考虑下下个节点
				ms.stack[ms.top].p = ms.stack[ms.top].p->next;					
		}

	}
	if (wayCount == 0)
		return false;
	else
		return true;

}

//给出起点和终点在图中寻找所有路径(用递归实现)
void FindWayfromMapbyRecursion(VNode * m,int start,int stop, MapStack * st,int &count)
{
	if ((m + start)->IsAvailable != true)
		return ;
	st->stack[++st->top].id = start;
	(m + start)->IsAvailable = false;
	if (st->stack[st->top].id == stop)								//找到一条路径并输出
	{
		printf("第%d条路径:\t",++count);
		for (int i = 0; i <= st->top; i++)
			printf("->%d",st->stack[i].id);
		printf("\n");
	}
	else{
		ArcNode * temp = (m + start)->firstarc;
		while (temp != NULL){										//循环处理周围节点
			FindWayfromMapbyRecursion(m, temp->id, stop, st, count);
			temp = temp->next;
		}
	}
	st->top--;
	(m + start)->IsAvailable = true;

}


//销毁图
void DestroyMap(VNode *m)
{
	ArcNode * temp=NULL,*p = NULL;
	for (int i = 0; i < MaxNode; i++){
		temp = (m + i)->firstarc;
		if ((m + i)->id != -1){
			while (temp != NULL){
				p = temp->next;
				free(temp);
				temp = p;
			}
		}
	}
}

//主函数
int _tmain(int argc, _TCHAR* argv[])
{
	AdjList m;														//定义图的邻接表头结点数组

	int start = 0, stop = 14, must = 6, mustnot = 12;

	for (int i = 0; i < MaxNode; i++){								//初始化头结点数组
		m[i].id = -1;
		m[i].IsAvailable = false;									//设置每个节点状态为不可使用
	}

	if (!FiletoMap(m)){												//从文件中创建图的邻接表类型
		printf("文件读取失败,错误不可修复,即将退出!\n");
		system("PAUSE");
		return -1;
	}

	printf("%d到%d路径为:\n",start, stop);
	if (!FindWayfromMap(m, start, stop))
		printf("NULL!\n");
	printf("\n");

	printf("%d到%d且必须经过%d的全部路径为:\n", start, stop,must);
	if (!FindWayfromMap(m, start, stop,must))
		printf("NULL!\n");
	printf("\n");

	printf("%d到%d且必须不能经过%d的全部路径为:\n", start, stop,mustnot);
	if (!FindWayfromMap(m, start, stop,-1, mustnot))
		printf("NULL!\n");
	printf("\n");

	MapStack ms;
	ms.top = -1;
	int count = 0;
	printf("%d到%d路径为:\n", start, stop);
	FindWayfromMapbyRecursion(m,start,stop,&ms,count);
	if (count == 0)
		printf("NULL\n");

	printf("\n销毁图...\n\n");
	DestroyMap(m);

	system("PAUSE");
	return 0;
}


/******************************************************************************
*说明:
*要求图的编号必须从0开始,且不能超过MaxNode
*必须包含某节点求路径函数名和寻找全部路径相同,但是需要将必须节点的id当做第三个参数传进函数
*必须不能包含某节点求路径函数名与求全部路径函数相同,但是需要将-1传进第三个参数,第四个参数传必须不能经过的节点
*******************************************************************************/
一个例子的代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值