【华为笔试】模块依赖关系判断

题目描述:
一个系统的若干模块之间存在互相依赖的关系,如果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}

从题目的描述可以简化为,从一个已存在的链表中,找出并标记其中自行成环的节点,结果每个节点的状态作为输出。参考静态链表的存储方式,建立映射表map,以键值的方式将输入的依赖关系进行存储。

由于输入的数据以固定的格式输入,且ID是以十六进制的方式输入,由于题目并未给予输入行数作为输入条件,而是以最后一行最后是否有“,”作为终止输入条件,因此采用getline()函数读取每一行,对每一行中的数字进行解析,以键值的方式建立map表,其中第一个数字为first,第二个数字为second。每次读取一行解析到最后,判断最后一个字符释放为“,”。如果最后一个字符是“}”而不是“,”,即表明输入已经结束,必须break。至此读取数据完毕。

在读取每对依赖关系的过程中,把每个数字都建立另外的一个map表,用于记录其是否在某个环内,同时为了最后结果输出。由于输入的ID可能为0x00,因此存在着某个非0值的ID指向了0值的依赖关系。由于使用的是map存储,其second表示的是下一个ID值。当某个值在map表中查找,如果该值在表中不存在,返回了0,同时会在表中建立该值,并赋值为0,如此一来会导致原来的存储改变而混乱。因此另外建立一个表,记录每对依赖关系的第一个ID,在数据输入中,每对依赖关系的第一个ID在map表中的值都1,如果不是第一个ID,即使后来查找中被建立,但初始值为0,不影响判断。综上,需要建立三个map表:一个记录原有依赖关系【data】,一个记录每对依赖关系的起点ID【dlog】,一个记录其状态(即是否存在环中)【out】。

在环形判断中,由于map表会根据键值在建立时进行排序,因此保证了每个键值都是有序的。在data上从某个ID开始,判断out[id]1是否为1,如果为1,说明其已经在某个环内,无须重复判断,进入其下一个;如果不在某个环中,则进入循环检测过程:首先将不存在环形中的ID记录在一个临时数组中,检查该ID所指向的下一个ID是否存在于该临时数组中,由于该数组保存在历史路径,如果当前的下一个ID能在临时数组中找到,那么说明历史数字中的所有节点已经构成了一个环,把该临时数组中的ID,在out这个map表上做标记,记录这些ID是在环中。如果下一个ID在临时数组中找不到,进入下一个循环。循环判断上,首先判断下一个ID是否存在着链路,检查dlog这个map表中,dlog[id]是否为1,如果为1,继续上述判断过程;如果不为0,那么说明到了该节点,已经不存在下一条链路,退出本次循环。

例如存在着下面的依赖关系:

0     ---      1

1     ---      3

2     ---      4

3     ---      0

从data这个map表第一个开始,取出0,由于0在out表上此刻还不是在某个环中,进入环形判断过程。将0放入临时数组中,检查下一个ID1是否在临时数组中,返回不存在,进入下一个循环。循环中检查1在dlog中是否为1,即是否存在下一条通路,返回为1,再将1放入临时数组中,检查下一个ID3是否已在临时数组中,返回不存在,进入下一个循环。继续检查3是否存在下一条通路,返回1即存在,检查下一个ID0是否已在临时数组中,返回结果为存在,此时表明,0,1,3这三个节点构成了一个环形,通过把临时数组中的所有节点在out这个map表上做结果标记,之后退出循环体。因为前面是临时数组,在退出本次循环后会自动清楚,不会影响下一个判断。

当判断下一个ID1时,检查其out表发现为1,表明其已经在某个环中当中,那么不进入环形判断,继续下一个。

当判断下一个ID2时,检查其out表发现为0,说明不在环形中,进入内循环判断,当检查到4不在临时数组中,进入下一个循环,通过判断dlog[id]得知4该节点不存在下一个指向,那么说明这两个不在环中,结束本次循环,继续下一个;

当判断下一个ID3时,由于已经是在某个环中,故而不进入内循环判断,此时所有依赖关系判断完毕,其结果都在out这个map表中。

具体程序如下:

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
using namespace std;

int main()
{
	while (1)
	{
		map<long long, long long> data;
		map<long long, int> out, dlog;
		string s;
		//输入数据,并对数据定位,建立map表
		while (getline(cin, s))
		{
			long long a = 0, b = 0;
			int i = 3;
			for (; s[i] != ','; i++)
				a += a * 16 + s[i] - '0';
			
			i += 4;
			for (; s[i] != '}'; i++)
				b += b * 16 + s[i] - '0';

			data[a] = b;
			dlog[a] = 1;
			out[a] = 0;
			out[b] = 0;
			if (i == s.length() - 1)
				break;
		}
		
		map<long long, long long>::iterator it = data.begin();
		for (; it != data.end(); it++)
		{
			if (0 == out[it->first])
			{
				vector<long long> tmp;
				long long t = it->first;
				while (1 == dlog[t])
				{
					tmp.push_back(t);
					if (find(tmp.begin(), tmp.end(), data[t]) != tmp.end())
					{
						for (vector<long long>::iterator k = tmp.begin(); k != tmp.end(); k++)
							out[*k] = 1;
						
						break;
					}
					t = data[t];
				}
			}
		}
		int sum=out.size();
		for (map<long long, int>::iterator kk = out.begin(); kk != out.end(); kk++)
		{
			sum--;
			cout<<"{0x"<<hex<<kk->first<<", ";
			if(k->second==1)
				cout<<"ture}";
			else
				cout<<"false}";
			
			if(sum==0)
				cout<<endl;
			else
				cout<<","<<endl;
		}
	}

	return 0;
}




  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值