模块依赖关系问题(一个系统的若干模块之间存在互相依赖的关系,如果A模块调用了B模块的接口)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Aoulun/article/details/79967070
一个系统的若干模块之间存在互相依赖的关系,如果A模块调用了B模块的接口,那么成为A依赖B,记为A->B
如果A->B,B->A,那么称A和B模块都存在循环依赖。
如果A->B,B->C,C->D,D->B,那么BCD存在循环依赖,A不存在循环依赖,以此类推
先输入若干模块之间的关系,判断某模块是否存在循环依赖。模块ID范围为0--0xffffffff

调用者保证相同的关系不重复输入

输入:

模块间关系,注意最后一行没有“,”结尾

输出描述:
模块是否循环依赖,注意最后一行没有“,”结尾

样例:

输入:

{0x00, 0x01},
{0x02, 0x03},
{0x03, 0x04}

输出:
{0x00, false},
{0x01, false},
{0x02, false},
{0x03, false},

{0x04, false}


代码(没有优化,只实现功能)

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <map>
#include <string>
#include <vector>

using namespace std;

multimap<unsigned int, unsigned int> orgD;  // A -> B
map<unsigned int, string> fPrt;
map<unsigned int,int> N;  // 保存所有的节点
map<unsigned int, bool> St;  // 保存节点是否为有环

// 用来保存轨迹,如果1->2,那么就把1和2都加到里面,如果1->2, 1->3, 当访问完2的时候,把2去除,同时把3加到里面
vector<unsigned int> trace;  

// 这个函数里面还增加代码,如果有环,就打印这个环
void gothrough(	multimap<unsigned int, unsigned int>* pSrcD,
				map<unsigned int, int>* pVist,
				unsigned int vstNumtmp)
{
	if ((*pVist).count(vstNumtmp) > 0 && (*pVist)[vstNumtmp] == 1) // 表示当前这个节点已经被访问过了,那么是存在环的
	{
		// 下面是添加打印每个环的程序,这个是有问题的
		/*
		vector<unsigned int>::iterator iteV;
		iteV = find(trace.begin(), trace.end(), vstNumtmp);
		if (iteV != trace.end())
		{
			auto idx = distance(begin(trace), iteV);
			St[vstNumtmp] = true;
			while (idx < trace.size())
			{
				printf("%d->",trace.at(idx));
				idx++;
			}
			return;
		}
		*/
		// 下面只是一个判断有无环的程序
		vector<unsigned int>::iterator iteV;
		iteV = find(trace.begin(), trace.end(), vstNumtmp);
		if (iteV != trace.end())
		{
			St[vstNumtmp] = true;
			return;
		}
	}

	// 否则这个节点就没有被访问过
	(*pVist)[vstNumtmp] = 1; // 把这个节点置为已经访问过了
	trace.push_back(vstNumtmp); // 把这个节点存到数组里面

	typedef multimap<unsigned int, unsigned int>::iterator CIT;
	typedef pair<CIT, CIT> Rng;
	Rng range = pSrcD->equal_range(vstNumtmp);
	for (CIT i = range.first; i != range.second; i++)
	{
		vstNumtmp = i->second;
		gothrough(pSrcD, pVist, vstNumtmp);
	}

	trace.pop_back();
}

void AddDependency(unsigned int Moduleld, unsigned int DependMoudleId)
{
	orgD.insert(make_pair(Moduleld, DependMoudleId));
	//orgD.insert(pair<unsigned int, unsigned int>(Moduleld, DependMoudleId));
	//orgD[Moduleld] = DependMoudleId;
}

// 这个地方应该有误解,如果输入某个点的话,如果有环,那么在搜索的时候,肯定返回到这个地方,
// 所以在设计算法的时候,没有必要把所有的节点都判断一遍,只需要在输出的时候,调用这个函数即可,
// 要不然很麻烦
bool MoudleIsCycularDependency(unsigned int ModuleId)
{
	if (orgD.count(ModuleId) == 0)  // 如果在map的左边一列中找不到的话,那么肯定就不是有环的点
		return false;
	else if (St[ModuleId])  // 已经是true,就没必要再搞一遍了
		return St[ModuleId];
	else// 否则的话,就开始遍历,如果能回到这个点,就是有环的点,否则就不是有环的点
	{
		// 开始的时候所有节点没有被访问过
		map<unsigned int, int> visit;
		gothrough(&orgD,  &visit, ModuleId);
		if (St[ModuleId])
			return true;
		else
			return false;
	}
}



void clear(void)
{
	orgD.clear();
	fPrt.clear();
	N.clear();
	trace.clear();
	St.clear();
}

int main()
{

	while (1)
	{
		string orgS;
		string tmp1, tmp2;
		unsigned int T = 0;

		while (getline(cin, orgS))
		{
			unsigned int ModuleID = 0, DependMoudleID = 0;
			int i;
			for (i = 3; orgS[i] != ','; i++)
			{
				ModuleID += ModuleID * 16 + orgS[i] - '0';
			}
			tmp1 = orgS.substr(1, i - 1);
			fPrt[ModuleID] = tmp1;

			int j;
			for (j = i + 4; orgS[j] != '}'; j++)
			{
				DependMoudleID += DependMoudleID * 16 + orgS[j] - '0';
			}
			tmp2 = orgS.substr(i + 2, j - (i + 2));
			fPrt[DependMoudleID] = tmp2;

			AddDependency(ModuleID, DependMoudleID);
			N[ModuleID] = 0;  // 在数组的最后添加这个元素
			N[DependMoudleID] = 0;

			if (orgS[j + 1] != ',')
				break;
		}

		map<unsigned int,int>::iterator it;
		it = N.begin();
		int toal = N.size();
		for (; it != N.end(); it++)
		{
			toal--;
			if (MoudleIsCycularDependency(it->first))
				printf("{%s, true}", fPrt[it->first].c_str());
			else
				printf("{%s, false}", fPrt[it->first].c_str());

			if (toal != 0)
				printf(",\n");
			else
				printf("\n");
		}
		clear();
	}

	return 0;
}

我的一些测试用例:

// 有断点,无循环
{0x00, 0x01},
{0x02, 0x03},
{0x03, 0x04}


{0x00, false},
{0x01, false},
{0x02, false},
{0x03, false},
{0x04, false}


// 有断点、有循环
{0x00, 0x01},
{0x01, 0x03},
{0x02, 0x04},
{0x03, 0x00}


{0x00, true},
{0x01, true},
{0x02, false},
{0x03, true},
{0x04, false}


// 无断点、无循环
{0x00, 0x02},
{0x02, 0x03},
{0x03, 0x04}


{0x00, false},
{0x02, false},
{0x03, false},
{0x04, false}


// 有断点、两个循环
{0x01, 0x02},
{0x03, 0x01},
{0x02, 0x03},
{0x04, 0x09},
{0x07, 0x05},
{0x05, 0x06},
{0x06, 0x07}


{0x01, true},
{0x02, true},
{0x03, true},
{0x04, false},
{0x05, true},
{0x06, true},
{0x07, true},
{0x09, false}


// 两个循环、其中一个有个把
{0x01, 0x02},
{0x03, 0x01},
{0x02, 0x03},
{0x04, 0x05},
{0x07, 0x05},
{0x05, 0x06},
{0x06, 0x07}


{0x01, true},
{0x02, true},
{0x03, true},
{0x04, false},
{0x05, true},
{0x06, true},
{0x07, true}


// 有循环、节点后面有分叉
{0x05, 0x01},
{0x01, 0x02},
{0x02, 0x04},
{0x02, 0x03},
{0x03, 0x01}


{0x01, true},
{0x02, true},
{0x03, true},
{0x04, false},
{0x05, false}


// 无循环、节点后有分叉
{0x01, 0x02},
{0x02, 0x04},
{0x02, 0x03}


{0x01, false},
{0x02, false},
{0x03, false},
{0x04, false}


// 有循环、节点后有分叉
{0x01, 0x02},
{0x02, 0x04},
{0x04, 0x01},
{0x02, 0x03},
{0x03, 0x05}


{0x01, true},
{0x02, true},
{0x03, false},
{0x04, true},
{0x05, false}


// 几点后有分叉、无循环
{0x01, 0x03},
{0x02, 0x05},
{0x01, 0x06},
{0x02, 0x07}


{0x01, false},
{0x02, false},
{0x03, false},
{0x05, false},
{0x06, false},
{0x07, false}


// 有循环,节点后有很多分叉
{0x05, 0x01},
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x06},
{0x02, 0x04},
{0x04, 0x01},
{0x04, 0x07}


{0x01, true},
{0x02, true},
{0x03, false},
{0x04, true},
{0x05, false},
{0x06, false},
{0x07, false}


// 循环带个把
{0x05, 0x01},
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x01}


{0x01, true},
{0x02, true},
{0x03, true},
{0x05, false}


// 大循环包裹小循环
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x01},
{0x01, 0x04},
{0x04, 0x05},
{0x05, 0x01}


{0x01, true},
{0x02, true},
{0x03, true},
{0x04, true},
{0x05, true}


// 有循环、节点后有分叉
{0x01, 0x02},
{0x02, 0x03},
{0x02, 0x04},
{0x03, 0x01},
{0x05, 0x01}


{0x01, true},
{0x02, true},
{0x03, true},
{0x04, false},
{0x05, false}


// 交叉循环
{0x05, 0x01},
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x04},
{0x04, 0x01},
{0x03, 0x07},
{0x07, 0x06},
{0x06, 0x04}




{0x01, true},
{0x02, true},
{0x03, true},
{0x04, true},
{0x05, false},
{0x06, true},
{0x07, true}


// 交叉循环
{0x05, 0x01},
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x04},
{0x04, 0x01},
{0x07, 0x03},
{0x06, 0x07},
{0x04, 0x06}


{0x01, true},
{0x02, true},
{0x03, true},
{0x04, true},
{0x05, false},
{0x06, true},
{0x07, true}


// 两个循环相连
{0x05, 0x01},
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x04},
{0x04, 0x01},
{0x04, 0x06},
{0x06, 0x07},
{0x08, 0x06},
{0x07, 0x08}


{0x01, true},
{0x02, true},
{0x03, true},
{0x04, true},
{0x05, false},
{0x06, true},
{0x07, true},
{0x08, true}


// 两个无关的环,有把
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x02},
{0x03, 0x04},
{0x04, 0x02},
{0x07, 0x08},
{0x08, 0x09},
{0x07, 0x09},
{0x09, 0x07}


// 两个相连的环,有把
{0x01, 0x02},
{0x02, 0x03},
{0x03, 0x02},
{0x03, 0x04},
{0x04, 0x02},
{0x07, 0x08},
{0x08, 0x09},
{0x07, 0x09},
{0x09, 0x07},
{0x03, 0x07}


{0x01, false},
{0x02, true},
{0x03, true},
{0x04, true},
{0x07, true},
{0x08, true},
{0x09, true}


猜你喜欢

转载自blog.csdn.net/Aoulun/article/details/79967070