// 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传进第三个参数,第四个参数传必须不能经过的节点
*******************************************************************************/
一个例子的代码
Map Find Way
最新推荐文章于 2020-03-06 15:14:35 发布