【复杂网络学习笔记】3:完整的小世界网络

*Error.h

 

#ifndef ERROR_H
#define ERROR_H
#include<iostream>
using namespace std;
//通用异常类
class Error
{
private:
	char message[100];//异常信息
public:
	Error(const char *mes = "一般性异常!"); //构造函数 
	~Error(void) {}; //析构函数	
	void Show() const; //显示异常信息
};

Error::Error(const char *mes)
{
	strcpy_s(message,100, mes); //复制异常信息
}

void Error::Show()const
{
	cout << message << endl; //显示异常信息	
}
#endif

 

 

*Arc.h

 

#ifndef NULL
#define NULL (void *)0
#endif

#ifndef ARC_H
#define ARC_H

//边节点类
struct Arc
{
	int iNum; //弧的另一端的节点的序号
	Arc* pNext; //指向下一边节点的指针

	Arc(int n, Arc* next); //构造序号为n,下一节点指向next的边节点
};
Arc::Arc(int n,Arc* next)
{
	iNum = n;
	pNext = next;
}
#endif

 

 

*Vex.h

 

#ifndef NULL
#define NULL (void *)0
#endif

#ifndef VEX_H
#define VEX_H
#include "arc.h"
struct Vex
{
	Arc* pFirst; //指向边节点表
	Vex();//空构造
};
Vex::Vex()
{
	pFirst = NULL;
}
#endif


*NetWork.h

 

 

#ifndef NULL
#define NULL (void *)0
#endif

#ifndef NETWORK_H
#define NETWORK_H
#include "vex.h"
#include "error.h"
#define VEXNUM 100 //测试的节点个数

//邻接网络(小世界模型)类
struct NetWork
{
	int vexNum; //顶点的数目
	Vex* vexTable; //顶点表

	NetWork(int v); //构造有v个顶点的空表
	void Clear(); //清空边节点
	void BuildArc(int a, int b); //构造从a到b的边
	void Step1(int n); //清空全表,然后形成n最近邻网络
	void Step2(int r); //以概率r%进行随机化重连
	void Show(); //简易的显示该网络
	void DelArc(int a, int b); //删除从a到b的边
	bool HasArc(int a, int b); //查询是否有从a到b的边
};

NetWork::NetWork(int v) //构造有v个顶点的空表
{
	vexTable = new Vex[vexNum=v];
}

void NetWork::Clear() //清空边节点
{
	Arc* p;
	for (int i = 0; i < vexNum; i++)
	{
		p = vexTable[i].pFirst; //从第一个边节点开始
		while (p != NULL)
		{
			vexTable[i].pFirst = p->pNext; //first域连到p后去
			delete p; //删掉p
			p = vexTable[i].pFirst; //再次指向first的节点
		}
	}
}

void NetWork::DelArc(int a, int b) //删除从a到b的边
{
	if (a < 0 || b < 0 || a >= vexNum || b >= vexNum)
		throw Error("数组越界");
	if (a == b)
		throw Error("自身没有环");
	Arc *p,*q;
	//删除a->b
	if (vexTable[a].pFirst->iNum == b) //如果是第一个点
	{
		p = vexTable[a].pFirst;
		vexTable[a].pFirst = p->pNext;
		delete p;
	}
	else //如果不是第一个点
	{
		q = vexTable[a].pFirst; //q在p前
		p = q->pNext;
		while (p != NULL)
		{
			if (p->iNum == b) //找到了b的位置
			{
				q->pNext = p->pNext;
				delete p;
				break;
			}
			q = p;
			p = p->pNext;//向下走
		}
	}
	//删除b->a
	if (vexTable[b].pFirst->iNum == a) //如果是第一个点
	{
		p = vexTable[b].pFirst;
		vexTable[b].pFirst = p->pNext;
		delete p;
	}
	else //如果不是第一个点
	{
		q = vexTable[b].pFirst; //q在p前
		p = q->pNext;
		while (p != NULL)
		{
			if (p->iNum == a) //找到了a的位置
			{
				q->pNext = p->pNext;
				delete p;
				break;
			}
			q = p;
			p = p->pNext;//向下走
		}
	}
}

bool NetWork::HasArc(int a, int b) //查询是否有从a到b的边
{
	if (a < 0 || b < 0 || a >= vexNum || b >= vexNum)
		throw Error("数组越界");
	if (a == b)
		return 0;
	Arc* p;
	bool k = 0; //k=1时表示从a到b有边
	p = vexTable[a].pFirst; //不妨看a->b有没有,从第一个边节点开始
	while (p != NULL) //检索是否已经有边
	{
		if (p->iNum == b) //检索到,做标记并跳出
		{
			k = 1;
			break;
		}
		p = p->pNext; //没检索到,继续找
	}
	return k;
}

void NetWork::BuildArc(int a, int b) //建立从a到b的边
{
	if (a < 0 || b < 0 || a >= vexNum || b >= vexNum)
		throw Error("数组越界");
	if (a == b)
		throw Error("不能自身成环");
	Arc* p;
	bool k = 0; //k=1时表示从a到b有边
	p = vexTable[a].pFirst; //不妨看a->b有没有,从第一个边节点开始
	while (p != NULL) //检索是否已经有边
	{
		if (p->iNum == b) //检索到,做标记并跳出
		{
			k = 1;
			break;
		}
		p = p->pNext; //没检索到,继续找
	}
	if (k == 0) //如果没有边,建立之
	{
		vexTable[a].pFirst = new Arc(b, vexTable[a].pFirst); //a能找到b同时
		vexTable[b].pFirst = new Arc(a, vexTable[b].pFirst); //b也要能找到a
	}
}

void NetWork::Step1(int n) //清空全表,然后形成n最近邻网络
{
	if (n > vexNum - 1)
		throw Error("n超限");
	if (n % 2 != 0)
		throw Error("n最近邻网络中n应为偶数");
	Clear(); //清空
	for (int i = 0; i < vexNum; i++) //对每个节点i
	{
		for (int j = 1; j <= n / 2; j++) //建立其n最近邻关系
		{
			BuildArc(i, (i + j) % vexNum); //向后第j个
			BuildArc(i, (i - j + vexNum) % vexNum); //向前第j个
		}
	}
}

void NetWork::Step2(int r) //以概率r%进行随机化重连
{
	if (r<0 || r>100)
		throw Error("随机化重连的概率不合法");
	int a, b; //辅助游标
	Arc* p; //辅助指针
	for (a = 0; a < vexNum; a++) //对于每个节点
	{
		p = vexTable[a].pFirst; //从第一条边开始
		while (p != NULL) //对于每条边
		{
			//生成0~99的伪随机数,它小于r的概率应为r%
			if (rand() % 100 < r && a<p->iNum) //只做左边比右边边小的
			{
				//这里是随机化重连过程
				//删除a->旧点和旧点->a的关系
				DelArc(a, p->iNum); //双向删除从a到p->iNum的边
				//随机地找一个之前和a无连接的新点
				do
				{
					b = rand() % VEXNUM;
				} while (b==a || HasArc(a,b)==1);//如果有边或者不合法就刷新b,直到a,b没有边
				//增加a->新点和新点->a的关系
				BuildArc(a, b);//建立新的边
			}
			p = p->pNext; //边向右走
		}
	}
}

void NetWork::Show() //显示
{
	Arc* p; //辅助指针
	for (int i = 0; i < vexNum; i++)
	{
		cout << i << ":";
		p = vexTable[i].pFirst; //从第一条边开始
		while (p != NULL) //对于每条边
		{
			cout <<"->"<< p->iNum;
			p = p->pNext;
		}
		cout << endl;
	}
}
#endif


*xsj.cpp

 

 

//#pragma warning(disable:4996) //忽略strcpy()函数不安全的warnning
#include "stdafx.h"
#include <iostream>
#include "NetWork.h" //邻接网络(小世界模型)类
using namespace std;


#define N 4 //最近邻网络个数
#define R 60 //随机化重连的概率*100

int _tmain(int argc, _TCHAR* argv[])
{
	try{
		NetWork *pNet = new NetWork(VEXNUM); //建立VEXNUM个节点的空邻接网络
		pNet->Step1(N); //形成N最近邻网络
		pNet->Step2(R); //以概率R%随机化重连
		pNet->Show(); //显示看一下
		system("pause");
		return 0;
	}
	catch (Error er)
	{
		er.Show();
	}
}

 

运行结果:

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值