您的位置:首页 > 理论基础 > 计算机网络

生成蜂窝网络图

2012-12-22 21:15 106 查看

有蜂窝网络如图,从1开始,按顺时针方向编号。要求给一个蜂窝数目N,得到整个蜂窝网络的图。

设每个节点周边的六个方向,按顺时针为 d1~d6。

思路就是根据当前的一个节点,要发展出下一个节点,那么下一个节点在当前节点的哪个方向上?经过分析,有如下3个规则:

规则1:以当前节点base为基础,按d1~d6方向发展新的节点。比如以1为基础,顺时针发展出2、3、4、5、6、7

在节点1的d6方向上发展出7后,节点1的d1方向已经被节点2占据,不能再发展出新节点了,那么以节点7为起点,从d1方向发展出节点8。这样,得到

规则2:若节点base的下一个方向上已不能发展出新节点了,则将最新发展出的节点作为新的base,继续根据规则1进行发展。

在规则1、2的指导下,发展出了节点8、9、10。节点10在节点9的d3方向。此时节点9的d4方向已经被占据,节点10成为base,但节点10的d4方向也被占据了。根据下一步走向,得到

规则3:如果base节点不能再新方向上发展新节点,且base已经是最新的节点了,那么就继续在原方向上发展新节点,且新节点立即成为base。

根据规则3,在节点10的d3方向上,发展出节点11,且节点11立即成为base,在d4方向上,可以发展出节点12。

按以上3条规则来生成新的节点,且注意在生成节点时,旧节点的周边节点也会与新节点产生联系,就可以生成N个节点的蜂窝网络图。

不过这几条规则还可以再简化一些:

实际上只有节点1可以发展出一圈新节点来。后续所有的节点,因为在内侧必然都已经有节点(生成顺序就是先内侧再外侧),因此节点1~7的图直接预置,规则1就可以不要了。

除了节点1之外,因为要紧贴内侧节点顺时针发展,所以每个节点其实只有一个可供发展的方向,因此规则2、3可以合并成终极规则:新发展的节点立即成为base,向下一个方向发展;如果不成功,则保持原方向发展。

节点连接问题:

从a发展出b以后,a周围的节点也要跟b联系起来,假设b在a的dx方向,那么a的dx+1和dx-1方向的节点也要与b联系起来。

a[dx+1]的节点,通过dx-1方向联系b;a[dx-1]方向的节点,通过dx+1联系b。因为相邻节点还有相邻节点,所以这是个递归的过程。

至于b,是个新几点,它的所有相邻节点都来至于老节点与它的连接,所以就不需要再递归了。

代码:

class Cellular
{
public:
void Generate(int iMaxCells);

Cellular();
~Cellular();
private:
enum ASPECT_E
{
ASPECT_S  = 0,
ASPECT_SW = 1,
ASPECT_NW = 2,
ASPECT_N  = 3,
ASPECT_NE = 4,
ASPECT_SE = 5,
ASPECT_BUTT
};
#define OPPOSITE_ASPECT(x) ((x<3)?(x+3):(x-3))
#define NEXT_ASPECT(x)     (((x+1) >= ASPECT_BUTT)?(ASPECT_S):(x+1))
#define FORE_ASPECT(x)     ((x == 0)?(ASPECT_SE):(x-1))

struct CELL
{
int iNeighbor[ASPECT_BUTT];
};
CELL *m_astCells;
ASPECT_E m_eCurAspect; // 生成最近一个节点时,相对于次近节点的方向
// 新的节点,将在最近生成节点的顺时针下一个方向,或者还是保持原方向
bool NewNeighbor(const int iOld, const int iNew, const ASPECT_E eAspect);
};

Cellular::Cellular()
{
this->m_astCells = NULL;
}

Cellular::~Cellular()
{
if (NULL != this->m_astCells)
{
delete [] this->m_astCells;
}
}

bool Cellular::NewNeighbor(const int iOld, const int iNew, const ASPECT_E eAspect)
{
// 当iOld无效时,直接返回。这种情况是存在的,比如从B发展出C后,还要考虑A与C是否相邻,
// 因此递归调用此函数来将C加成A的邻居。但实际上A可能不存在。
if (0 == iOld)
{
return true;
}

// 如果在old的aspect上,已经有一个cell,且不是要新增这个,说明无法在这个方向上发展了
// 但如果与新增的cell相同,说明这个方向上已经发展出来了,不用重复发展
if (this->m_astCells[iOld].iNeighbor[eAspect] != 0)
{
if (this->m_astCells[iOld].iNeighbor[eAspect] != iNew)
{
return false;
}
else
{
return true;
}
}

this->m_astCells[iOld].iNeighbor[eAspect] = iNew;

// 从旧cell生成新cell后,旧cell周边的cell也可能与新cell产生联系
ASPECT_E eNextAspect = (ASPECT_E)NEXT_ASPECT(eAspect);
ASPECT_E eForeAspect = (ASPECT_E)FORE_ASPECT(eAspect);
NewNeighbor(this->m_astCells[iOld].iNeighbor[eNextAspect], iNew, eForeAspect);
NewNeighbor(this->m_astCells[iOld].iNeighbor[eForeAspect], iNew, eNextAspect);

// 新cell也要倒过来指向旧cell
int iOpposite = eAspect < 3?(eAspect+3):(eAspect-3);
this->m_astCells[iNew].iNeighbor[iOpposite] = iOld;

return true;
}

void Cellular::Generate(int iMaxCells)
{
this->m_astCells = new CELL[iMaxCells+1];
if (NULL == this->m_astCells)
{
return;
}

for (int i = 0; i <= iMaxCells; i++)
{
for (int j = ASPECT_S; j < ASPECT_BUTT; j++)
{
this->m_astCells[i].iNeighbor[j] = 0;
}
}

// 先预置Cell 1 到 7的网络
this->NewNeighbor(1, 2, ASPECT_S);
this->NewNeighbor(1, 3, ASPECT_SW);
this->NewNeighbor(1, 4, ASPECT_NW);
this->NewNeighbor(1, 5, ASPECT_N);
this->NewNeighbor(1, 6, ASPECT_NE);
this->NewNeighbor(1, 7, ASPECT_SE);

// 再生成剩下的cells
this->m_eCurAspect = ASPECT_SE;
for (int iCell = 7; iCell < iMaxCells; iCell++)
{
ASPECT_E eAspect = (ASPECT_E)NEXT_ASPECT(this->m_eCurAspect);
if (true == NewNeighbor(iCell, iCell+1, eAspect))
{
this->m_eCurAspect = eAspect;
}
else
{
(void)NewNeighbor(iCell, iCell+1, this->m_eCurAspect);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: