📄 7.m
字号:
%生成网络部分
%第一步:随即分布1000个点,并用三维立体图绘出各点位置。
M=0.0000001;
for k=1:1000
%if(k==1)
% P(1).x=5000;
% P(1).y=5000;
% P(1).z=5000;
%else
P(k).x=fix(10000*rand);
P(k).y=fix(10000*rand);
P(k).z=fix(10000*rand);
hold on
plot3(P(k).x,P(k).y,P(k).z,'.');
if(k==1000)
title('1000个传感器随机分布图');
end
%end
P(k).energy=100;%初始的节点能量为100J
P(k).cid=0;%初始化节点网络号
P(k).id=k;
P(k).next=0;%初始化下一点为0
P(k).level=1;%初始化节点的层次号为最低层号1,最高层层号为3
P(k).out=0;%初始化节点的初始发射功率
P(k).num=0;%初始化节点的邻节点数
%新增的用于头节点路由得参数
P(k).ort=0;%为簇头跳跃的下一点地址(假设簇头之间的跳跃最多3次),一跳的平均距离为3000
P(k).sur=0;%为头节点处在根节点的第几层的外围标示,因为最多3跳,所以范围在1~3之间
%
end
fprintf('根节点的坐标为:');
disp([P(1).x P(1).y P(1).z]);%检验是否各点分布正常。
sur(1)=0;%纪录外围1的节点数
sur(2)=0;%纪录外围2的节点数
shot=50000;%用于纪录最短的路径,使用一个不可能存在的数值
shotnum=0;%纪录最短路径点的序号
time=0;%初始化时间记录变量----(由于各网络间是平行的所以其时间按含有最大子节点的网络时间计算,按轮计数)
account=0;%初始化传输数据变量----(因为每次通信的信息量固定,所以以通信次数统计通信量)
cidnum=0;%网络数
%第二步:构建网络。
%因为范围在10000*10000*10000内,所以可以计算出每个网络簇的大概范围,每个节点的平均范围为1000*1000*1000两点间的平均距离为1417。设一个簇有N个节点,又要求两跳内必须传至根节点,所以
%只能有两层网络。每个簇的平均大小应该为1+N+N*N=1000,所以N=31。所以认为每簇内节点数在27~35之间是合理的。最底层的网络范围
%为2771
%广播生成最低层网络
h=1;%网络头链表的指针
for w=1:1000
if(( P(w).cid==0)&(P(w).level==1))%若n点未处于任何一个网络且位于最底层
P(w).cid=w;%修改自己的网络号
head(h).id=w;%写入网络头链表
h=h+1;%向后爬行
P(w).level= P(w).level+1;%修改自己的层号,以为作为簇头所以层号上升1
x=w+1;%用于向后续的点广播该点
next=w;
cidnum=cidnum+1;%网络数增加1
fprintf('网络%d的节点有:\n',P(w).id);
for k=x:1000%向后续点广播该点
N1=fix(sqrt((P(w).x-P(k).x)^2+(P(w).y-P(k).y)^2+(P(w).z-P(k).z)^2));%距离公式
if((N1<=2771)&(P(k).cid==0))%在广播范围内且未处于任何一个网络中
P(next).next=k;
next=k;%该节点位于第P(n).level层的下一个邻节点
P(next).cid=w;%修改该点的网络号
P(w).num=P(w).num+1;
fprintf('%d ',P(next).id);
P(k).out=M*N1^2;%暂时假设最后的广播功率
end
end
fprintf('\n');
end
end
fprintf('共有%d个网络。\n',cidnum);
fprintf('头节点分别是:');
fprintf('\n');
for j=1:cidnum
fprintf('%d ',head(j).id);
%加入网络外围路由
P(head(1).id).sur=100;%定义一个超范围的数以区分根节点
N2=fix(sqrt((P(head(j).id).x-P(1).x)^2+(P(head(j).id).y-P(1).y)^2+(P(head(j).id).z-P(1).z)^2));%距离公式
if(N2<=6928)
P(head(j).id).ort=head(1).id;
P(head(j).id).sur=1;
P(head(j).id).out=M*N2^2;%修改头节点到根节点的传输功率
end
end
fprintf('\n');
fprintf('外围一层节点头节点分别是:');
for j=1:cidnum
if(P(head(j).id).sur==1)
sur(1)=sur(1)+1;
fprintf('%d ',head(j).id);
end
end
fprintf('\n');
%建立第二层外围簇头节点
fprintf('外围二层节点头节点分别是:');
for j=1:cidnum
if(P(head(j).id).sur==0)
sur(2)=sur(2)+1;
for v=1:cidnum
if((P(head(v).id).sur==100)|(P(head(v).id).sur==1))
N4=fix(sqrt((P(head(j).id).x-P(head(v).id).x)^2+(P(head(j).id).y-P(head(v).id).y)^2+(P(head(j).id).z-P(head(v).id).z)^2));%距离公式
if(N4<shot)
shot=N4;
shotnum=head(v).id;
end
end
end
if(shotnum==1)
P(head(j).id).sur=1;
sur(2)=sur(2)-1;
sur(1)=sur(1)+1;
else
P(head(j).id).sur=2;
end
P(head(j).id).out=M*shot^2;
P(head(j).id).ort=shotnum;
fprintf('%d(%d) ',head(j).id,shotnum);
end
end
fprintf('\n');
h=h-1;%最后多加的一点要减去
%绘图部分
figure
hold on
plot3(P(1).x,P(1).y,P(1).z,'r:p');
for i=1:1000
hold on
if(P(i).sur==1)
plot3(P(i).x,P(i).y,P(i).z,'b:s');
end
if(P(i).sur==2)
plot3(P(i).x,P(i).y,P(i).z,'k:o');
end
if(i==1000)
title('各头节点的层次图');
end
end
figure
hold on
plot3(P(1).x,P(1).y,P(1).z,'r:p');
for i=1:1000
hold on
if(P(i).sur==1)
plot3(P(i).x,P(i).y,P(i).z,'b:s');
end
if(P(i).sur==2)
plot3(P(i).x,P(i).y,P(i).z,'k:o');
end
if(P(i).sur==0)
plot3(P(i).x,P(i).y,P(i).z,'g:.');
end
if(i==1000)
title('最终的网络层次图');
end
end
while(1)
n10=input('请输入您想观察的网络号(退出请输入"0")\n');
if(n10==0)
break
else
while(P(n10).level~=2)
fprintf('输入错误!请从新输入\n');
n10=input('请输入您想观察的网络号\n');
end
z=n10;
figure
hold on
plot3(P(z).x,P(z).y,P(z).z,'r:d');
fprintf('该簇的节点有: %d ',n10);
while(P(z).next~=0)
hold on
plot3(P(P(z).next).x,P(P(z).next).y,P(P(z).next).z,'b:x');
fprintf('%d ',P(z).next);
z=P(z).next;
if(P(z).next==0)
title('该簇的结构图');
fprintf('\n');
end
end
end
end
fprintf('网络运行中,请稍等……\n');
%运行部分
%(加入路由部分后,因为认为路由结构不变了,所以本层只需在簇头能量用完时修改即可)
tr=2;
ti(1)=0;
ac(1)=0;
act(1)=0;
maxnum=0;%用于记录还有最多子节点的簇的子节点数
num=1000;%num为记录能量不为零的节点数
receive=0.0005; %接收所消耗的能量
head=1;%纪录根节点位置(因为开始时根节点必为1)为0时同样可以运行
while(num>1)
maxnum=0;
%底层通信(网络的路由结构不改变)
for k=1:1000 %子节点与簇头节点的通信,不会影响簇的数目(一次运行为一簇)
if(head==0)%若头节点无,则跳出本层循环。重新进行网络重组。
break;
end
if((P(k).level==2)&(P(k).energy>0 )&(P(k).next~=0))%若k为头节点,开始这一簇得的广播
m=k;%m用于移动
while((P(m).next~=0)&(P(k).energy>0))%簇内的各节点逐个的运行(负责一簇内的运行,一次运行为一簇内的一个子节点)
P(P(m).next).energy=P(P(m).next).energy-P(P(m).next).out;%发射节点能量损耗
if(P(P(m).next).energy<=0)%若最底层的子节点的能量耗尽,则删除该节点并修改邻接点链表
num=num-1;%总数减少了1
P(k).num=P(k).num-1;%该簇头子节点减少1
P(P(m).next).level=0;%作为能量耗尽的标示
fprintf('子节点%d ',P(m).next);%显示出能量耗尽的点的序号
P(m).next=P(P(m).next).next;%从链表中删除该点P(m).next
else %簇内的该子点的能量没有用完
P(k).energy=P(k).energy-receive;%底层能量未耗尽,则簇头减去接收所需的能量,receive为接收信号的固定损耗
if(P(k).energy<=0) %若头节点的能量耗尽;同时认为本簇的本次循环终止,系统会按顺序转入新的簇运行<修改头节点时不会影响到网络结构>
num=num-1;%总数减少了1
fprintf('头节点%d ',P(k).id);%输出该头节点
P(k).level=0;%作为能量耗尽的标示
P(P(k).next).level=2;%改变头节点。不用考虑P(k).next是否存在,因为如果不存在则不会出现头节点能量为零的情况
z=k;%z用于对头节点改造的计序
while(P(z).next~=0)%(内二层循环)用于对头节点的改造
P(P(k).next).num=P(P(k).next).num+1;%邻节点数加1
P(P(z).next).cid=P(k).next;%改变网络中各节点的头节点标识
P(P(z).next).out=M*(fix(sqrt((P(P(z).next).x-P(P(k).next).x)^2+(P(P(z).next).y-P(P(k).next).y)^2+(P(P(z).next).z-P(P(k).next).z)^2)))^2;%距离公式%改变至总簇头的传输能量%修改传输功率
z=P(z).next;%向后爬动
end%完成对各子节点的改造
if(P(k).next~=0)%如果上面的循环运行了,减去纪录自己的一次
P(P(k).next).num=P(P(k).next).num-1;%减去自己的一点
end
if(k==head)%如果是头节点则结构重组,跳过本次运行
head=0;
break;
end
%修改路由
P(P(k).next).sur=P(k).sur;
P(P(k).next).ort=P(k).ort;
%该点代替头节点链表中的位置,因为有后续节点代替所以簇数不会减少
%用后续节点取代原节点作中继节点
if(P(k).sur==1)%第一层的节点才有可能为中继节点
for i=1:1000
if(P(i).ort==k)
P(i).ort=P(k).next;
P(i).out=M*(fix(sqrt((P(P(k).next).x-P(i).x)^2+(P(P(k).next).y-P(i).y)^2+(P(P(k).next).z-P(i).z)^2)))^2;%距离公式,改变传输功率为至总簇头的传输能量
end
end
end
Q=P(P(k).next).ort;
P(P(k).next).out=M*(fix(sqrt((P(P(k).next).x-P(Q).x)^2+(P(P(k).next).y-P(Q).y)^2+(P(P(k).next).z-P(Q).z)^2)))^2;%距离公式,改变传输功率为至总簇头的传输能量
break;%因为簇头节点的能量用完了,所以需要跳出本簇该层的循环,即 while((P(m).next~=0)&(P(k).energy>0));提前结束本簇运行
else%若头节点的能量也没有用完,完成一次通信,并向后爬行
account=account+1;%完成一次通信
end%完成簇内的一次通信(头节点的能量没有用完)
end%子节点的能量没有用完
if(P(m).next~=0)
m=P(m).next;%向后爬行?????(存在问题:当改为在下个end之后就不对了)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -