CIDR步步模拟

CIDR合并:

按照题目中所给的方法进行模拟即可:

第一次用vector数据结构来进行处理:

 

#include<iostream>
#include<string>
#include<stdlib.h>
#include<vector>
#include<algorithm>
using namespace std; 
string int2bin1(long long num)
{
	string s="";
    int i;
    for(i = 1; i < 33; i++)
    {
       if((unsigned int)(num & 0x80000000) == (unsigned int)(0x80000000))
       {
           s=s+"1";
       }
       else
       {
           s=s+"0";
       }
       num = num << 1; 
    }
    return s;
}
struct node
{
	int t[4];
	int k;
	unsigned int value;
    string str;
	node(int q[4],int p)
	{
		for(int i=0;i<4;i++)
		t[i]=q[i];
		k=p;
		value=t[3]+t[2]*256+t[1]*256*256+t[0]*256*256*256;
		str=int2bin1(value);
	}
};
vector<node> vec;
int chnum(string str)
{
	int num=0;
	for(int i=0;i<str.size();i++)
	{
		if(str[i]>='0'&&str[i]<='9')
		num=num*10+str[i]-'0';
	}
	return num;
} 
bool cmp(node a,node b)
{
	if(a.value <b.value )
	return true;
	else if(a.value ==b.value &&a.k<b.k)
	return true;
	else
	return false;
}
bool flag(node a,node b)//判断b的匹配集是否是a的匹配集的子集 
{
	if(a.k>b.k)
	return false;
	for(long long i=0;i<a.k;i++)
	{
		if(a.str[i]!=b.str[i])
		return false;
	}
	
	return true;
} 
void merge1()
{
	vector<node>::iterator i=vec.begin();
	vector<node>::iterator j=vec.begin();
	for(++j;j!=vec.end();)
	{
		if(flag(*i,*j))
		{
			j=vec.erase(j);	 
		}
		else
		{
			++i;
			++j;
		}
	}
}
bool flaged(node a,node b) 
{
    if(a.k!=b.k)
	return false;
	for(int i=0;i<a.k-1;++i)
	{
		if(a.str[i]!=b.str[i])
		return false;
	}
	return a.str[a.k-1]!=b.str[a.k-1];
}
void merge2()
{
	vector<node>::iterator i=vec.begin();
	vector<node>::iterator j=vec.begin();
	++j; 
	for(;j!=vec.end();)
	{
		if(flaged(*i,*j))
		{
			j=vec.erase(j);	
			--(*i).k;
			//cout<<(*i).str<<endl;
           //cout<<(*i).k<<endl;
			if(i!=vec.begin())
			{
				--i;
				--j;
			 } 
		}
		else
		{
			++i;
			++j;
		}
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	string s;
	for(int i=0;i<n;i++)
	{
		//scanf("%s",s);
		cin>>s;
		//getline(cin,s);
		int t1=s.find(".");
		int t2=0;
		int temp[4];
		for(int i=0;i<4;i++)
		temp[i]=0;
		int temped=0;
		int count=0;
		while(t1!=s.npos)
		{
			temp[count++]=chnum(s.substr(t2,t1-t2));
			s[t1]='|';
			t2=t1+1;
			t1=s.find("."); 
		} 
		if(count==0)//证明是2/3或者2这种类型 
		{
			int t3=s.find("/");
			if(t3==s.npos)
			{
				temp[0]=chnum(s);
				count++;
				temped=8;
			}
			
			else
			{
				temp[0]=chnum(s.substr(0,t3));
				temped=chnum(s.substr(t3+1,s.length()-t3-1)); 
				count++;
			}
		//	temped=count*8;
		}
		else
		{
			int t3=s.find("/");
			if(t3!=s.npos)
			{
				temp[count++]=chnum(s.substr(t2,t3-t2));
				temped=chnum(s.substr(t3+1,s.length()-t3-1)); 
			}
			else
			{
				temp[count++]=chnum(s.substr(t2,s.length()-t2));
				temped=count*8;
			}	
		}
	//	for(int i=0;i<4;i++)
		//cout<<temp[i]<<" ";
	//	cout<<endl;
	//	cout<<temped<<endl;
	vec.push_back(node(temp,temped));
	}
	
	sort(vec.begin(),vec.end(),cmp);
//	for(int i=0;i<vec.size();i++)
//	cout<<vec[i].str<<" ";
	merge1();
	merge2();
	for(int i=0;i<vec.size();i++)
	{
		for(int j=0;j<3;j++)
		{
			printf("%d.",vec[i].t[j]);
		}
		printf("%d/%d\n",vec[i].t[3],vec[i].k); 
	}
	return 0;
}


 


第二次把vector改成list,由于list是双向链表,可以高效进行删除插入和排序操作,过了。

#include<iostream>
#include<string>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<list>
using namespace std; 
string int2bin1(long long num)//将10进制数转化为32位二进制数 
{
	string s="";//用来存储32位二进制数 
    int i;
    for(i = 1; i < 33; i++)
    {
       if((unsigned int)(num & 0x80000000) == (unsigned int)(0x80000000))//是在把十六进制表示的0x80000000和传递过来的num 的值进行位运算 &
       {
           s=s+"1";
       }
       else
       {
           s=s+"0";
       }
       num = num << 1; 
    }
    return s;
}
struct node
{
	int t[4];//0~3分别存储从高位到低位的数值,两者之间用.来进行分割 
	int k;//表示len 
	unsigned int value;//根据a3,a2,a1,a0转化为10进制数 
    string str;
	node(int q[4],int p)
	{
		for(int i=0;i<4;i++)
		t[i]=q[i];
		k=p;
		value=t[3]+t[2]*256+t[1]*256*256+t[0]*256*256*256;
		str=int2bin1(value);
	}
	bool operator<(node b)
   {
	if(value <b.value )
	return true;
	else if(value ==b.value &&k<b.k)
	return true;
	else
	return false;
    }
};
list<node> vec;
void fun1(node &d){
	cout << d.t[0]<< "." << d.t[1] << "."<<d.t[2]<<"."<<d.t[3]<<"/"<<d.k<<endl;//用于后边list类型的输出 
}
int chnum(string str)
{
	int num=0;
	for(int i=0;i<str.size();i++)
	{
		if(str[i]>='0'&&str[i]<='9')//将一个数字字符串转化为整数 
		num=num*10+str[i]-'0';
	}
	return num;
} 
bool flag(node a,node b)//判断b的匹配集是否是a的匹配集的子集 
{
	if(a.k>b.k)//作为父集,k一定要小于等于 
	return false;
	for(long long i=0;i<a.k;i++)
	{
		if(a.str[i]!=b.str[i])
		return false;
	}
	
	return true;
} 
void merge1()//进行第一步的合并 
{
	list<node>::iterator i=vec.begin();
	list<node>::iterator j=vec.begin();
	for(++j;j!=vec.end();)
	{
		if(flag(*i,*j))//如果j是i的子集,则删除j这个节点 
		{
			j=vec.erase(j);	 //list的erase函数返回的是删除之后的下一个元素的位置 
		}
		else
		{
			++i;
			++j;
		}
	}
}
bool flaged(node a,node b) //判断a和b的匹配集的并集是否等于a'的匹配集 
{
    if(a.k!=b.k)
	return false;
	for(int i=0;i<a.k-1;++i)
	{
		if(a.str[i]!=b.str[i])
		return false;
	}
	return a.str[a.k-1]!=b.str[a.k-1];//对于len的最后一位不相同,前边相同的情况则一定是并集的匹配集等于a的前缀和加上a的len-1 
}
void merge2()//第二部合并,同级合并 
{
	list<node>::iterator i=vec.begin();
	list<node>::iterator j=vec.begin();//迭代器 
	++j; 
	for(;j!=vec.end();)
	{
		if(flaged(*i,*j))//如果可以合并,删除j,i的len-1 
		{
			j=vec.erase(j);	
			--(*i).k;
			//cout<<(*i).str<<endl;
           //cout<<(*i).k<<endl;
			if(i!=vec.begin())//如果不是头节点,则一直返回到头节点进行比较 
			{
				--i;
				--j;
			 } 
		}
		else
		{
			++i;
			++j;
		}
	}
}
int main()
{
	int n;
	cin>>n;
	string s;
	for(int i=0;i<n;i++)
	{
		cin>>s;
		//getline(cin,s);
		int t1=s.find(".");//查询是否有. 
		int t2=0;
		int temp[4];
		for(int i=0;i<4;i++)
		temp[i]=0;//用来存储每个节点所对应的4个值 
		int temped=0;//用来存储每个节点的len 
		int count=0;
		while(t1!=s.npos)
		{
			temp[count++]=chnum(s.substr(t2,t1-t2));//将数字字符串转化为整数 
			s[t1]='|';//将所分析过的.掩盖 
			t2=t1+1;
			t1=s.find("."); 
		} 
		if(count==0)//证明是2/3或者2这种类型 
		{
			int t3=s.find("/");
			if(t3==s.npos)//证明是2这种类型 
			{
				temp[0]=chnum(s);
				count++;
				temped=8;
			}
			
			else
			{
				temp[0]=chnum(s.substr(0,t3));//证明是2/3这种类型 
				temped=chnum(s.substr(t3+1,s.length()-t3-1)); 
				count++;
			}
		//	temped=count*8;
		}
		else
		{
			int t3=s.find("/");//证明是2.3.4/3或者2.3.4这种类型 
			if(t3!=s.npos)
			{
				temp[count++]=chnum(s.substr(t2,t3-t2));//2.3.4/3这种类型 
				temped=chnum(s.substr(t3+1,s.length()-t3-1)); 
			}
			else
			{
				temp[count++]=chnum(s.substr(t2,s.length()-t2));//2.3.4这种类型 
				temped=count*8;
			}	
		}
	//	for(int i=0;i<4;i++)
		//cout<<temp[i]<<" ";
	//	cout<<endl;
	//	cout<<temped<<endl;
	vec.push_back(node(temp,temped));//在list后边实现插入 
	}
	vec.sort();//进行排序,在结构体中对<进行了重载 
//	sort(vec.begin(),vec.end(),cmp);
//	for(int i=0;i<vec.size();i++)
//	cout<<vec[i].str<<" ";
	merge1();//第一次合并 
	merge2();//同级合并 
	//for(int i=0;i<vec.size();i++)
	/*for(list<node>::iterator i=vec.begin();i!=vec.end();i++)
	{
		for(int j=0;j<3;j++)
		{
			cout<<(*i).t[j]<<".";
		}
		cout<<(*i).t[3]<<"/"<<(*i).k<<endl; 
	}*/
	for_each(vec.begin(), vec.end(), fun1);//输出list中现有节点的相关信息 
	return 0;
}

说明:对于整数转化为32位二进制数是借鉴部分博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值