模块相互依赖问题

原创 2018年04月16日 21:42:28
一个系统的若干模块之间存在互相依赖的关系,如果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}


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Aoulun/article/details/79967070

解决 Gradle 进行多模块开发时,模块相互依赖的问题

问题背景 在使用多模块开发时,通常一个模块(A)可能会需要其它模块(B)中的类或方法,这时就产生了依赖关系,也就是 A 依赖 B。 要解决上述依赖,有两种方案 1、将B发布到 repo 仓库(...
  • w_yunlong
  • w_yunlong
  • 2018-01-07 16:58:24
  • 654

Gradle 与 Android的相互依赖

Android应用的构建过程是一个复杂的过程,涉及到很多工具。首先所有的资源文件都会被编译,并且在一个R文件中引用,然后Java代码被编译,通过dex工具转换成dalvik字节码。最后这些文件都会被打...
  • halaoda
  • halaoda
  • 2017-11-24 11:02:26
  • 522

嵌入式开发第64日(内核模块的依赖)

内核模块依赖 一个模块使用了另一个模块的变量或者函数,第一个模块就依赖于第二个模块 #include #include MODULE_LICENSE("GPL v2"); exte...
  • Reasonss
  • Reasonss
  • 2016-11-08 00:09:59
  • 542

Android studio 两个项目相互依赖

Android studio 两个项目相互依赖 注意: 依赖包中含有全局变量定义:(Application);主项目中也含有全局变量(Application) 解决方式:让主application ...
  • u013472738
  • u013472738
  • 2017-01-11 13:36:51
  • 1033

Maven项目如果涉及多个模块的话,设计的时候就要考虑模块循环依赖的问题

Maven项目如果涉及多个模块的话,设计的时候就要考虑模块循环依赖的问题
  • u013803262
  • u013803262
  • 2017-03-17 15:49:04
  • 406

解决rpm包相互依赖问题

在安装RPM包时,如果遇到循环依赖的问题时,可以通过下面的方法来安装: 用*号通配符匹配此套件的所有RPM,并将所有相依赖的RPM包一起安装,同时加上 --aid的参数。 下面这条命令安装...
  • ttomqq
  • ttomqq
  • 2014-08-05 15:05:09
  • 2194

指南:设计中的导入依赖关系

依赖关系设计模型中的导入依赖关系是一种被赋予了构造型的依赖关系,其来源是一个设计包,而目标则是另外一个设计包。导入依赖关系导致目标设计包的公有内容可在源设计包中被引用。主题解释 使用 解释处理包之间的...
  • luckisok
  • luckisok
  • 2005-10-14 21:48:00
  • 821

Python模块依赖

用matplotlib软件包绘个图,但发现其还依赖一个库numpy 想测试一个库有没有或者依赖其他的库可以在命令行下执行import命令,如果没有它会打印出所依赖的库,如下图 ma...
  • lanbingg
  • lanbingg
  • 2013-04-07 18:08:30
  • 1092

spring是如何解决对象相互依赖的

第一种,解决setter对象的依赖,就是说在A类需要设置B类,B类需要设置C类,C类需要设置A类,这时就出现一个死循环, spring的解决方案是,初始化A类时把A类的初始化Bean放到缓存中,然后...
  • shenjianzhuang
  • shenjianzhuang
  • 2018-01-11 12:03:25
  • 118

Maven--多模块依赖实例解析(五)

这是最后一篇,做一个多模块依赖的正式例子,简单的讲一下单元测试、覆盖率以及发布和站点的部署。只想讲讲和Maven相关的东西,因此,注重看pom文件,里面具体的代码就不实现了,下面是我项目骨架: ...
  • StubbornPotatoes
  • StubbornPotatoes
  • 2013-09-30 14:42:57
  • 10970
收藏助手
不良信息举报
您举报文章:模块相互依赖问题
举报原因:
原因补充:

(最多只允许输入30个字)