GPSR基于节点地理位置路由信息,采用贪婪策略和右手准则的结合在邻居节点中选择下一跳节点进行数据转发。节点在进行路由选择时,只需知道自己、邻居和目标节点的地理位置信息,无需维护全局网络的链路状态,这在很大程度上降低了网络开销。同时,节点在数据转发时总是选择比自己近的且到目标节点距离最近的邻居节点作为下一跳。这不仅减少了所选路径的跳数,而且缩短了数据传输的路径总长度,整体降低了WSNs的能量消耗,能有效提高路径QoS时延性能和延长网络生命周期。
主程序代码如下: 
 %% GPSR路由算法改进
 %%所有传感器节点分配消息发送到目的地
 clear all;close all ;clc;%清除变量
 randn('state', sum(100*clock));
 %% ------------------参数设置开始------------------------------
 area_length = 100;%区域
 area_wide = 100;%区域
 Range = 20;%节点最大传递范围
 node_energy=100;%节点能源
 node_down=0.4;%节点能量衰减系数
 num_node = 60;  %节点数
 node_near=0.3;%节点紧致度,也即节点间距离不能小于0.3*Range
 sent_number=20;
 %% ------------------参数设置结束------------------------------
 %% --------------------坐标设置开始----------------------------
 %% 计算出目标节点坐标、源节点坐标、各路由节点几何位置
 node=node_position(area_length,area_wide,num_node,node_energy,Range,node_near);
% 计算距离表
 Dtable=distance_table(node);
 %计算拓扑结构表
 Ttable=topo_table(node,Range,Dtable);
 x=1:num_node;
 Ttable(x).topolopy;
 RNG_Ttable=RNG_topology(node,Dtable,Ttable);
 %% ----------------------坐标设置结束--------------------------
 %% -------------------计算距离表和拓扑关系----------------------
%% -------------------贪婪算法开始-------------
 route_length=zeros(sent_number,1);
 for k1=1:sent_number
     %随机生成源节点、目标节点
     s1=randperm(num_node);
     v1=find(s1==1);%源节点
     v2=find(s1==2);%目标节点
     %确定源节点、目标节点
     for i=1:num_node
         node(i).class=0;
         if i==v1
             node(i).class=1;
             number_source=i;
         end
         if i==v2
             node(i).class=2;
             number_dem=i;
         end
     end
     %计算距离
     distance_s2d=Dtable(number_source,number_dem);%距离初始化
     route=[number_source];%路径初始化
     Ttable01=Ttable;%临时拓扑赋值,防止搞坏原始拓扑集
     iter_number=0;
     %% GPRS主函数
     while distance_s2d~=0
         %% 判断死链
         if isempty(route)
             disp('能量耗尽,无法产生路由路径');
             break;
         end
         
         curr_node=route(end);%路径当前最后一个节点
         curr_topolopy=Ttable01(curr_node).topolopy;%获取当前拓扑相邻集合
         a03=numel(find(curr_topolopy==number_dem));
         if a03>0%存在
             route=[route number_dem];
             break;
         end
         
         %% ------------------删除curr_topolopy中属于route的节点开始-----
         n=length(route);%计算route长度
         for k=1:n
             v01=find(curr_topolopy==route(k));%route(k)是不是curr_topolopy的成员
             if numel(v01)>0%是成员
                 curr_topolopy(v01)=[];%删除该元素
             end
         end
         %% ------------------删除curr_topolopy中属于route的节点结束-----
         %% ------------------删除curr_topolopy中属于比route(end)离目的节点距离远的开始-----
         distance_route_end=Dtable(route(end),number_dem);
         distance_topolopy=Dtable(curr_topolopy,number_dem);
         v4=find(distance_topolopy<distance_route_end);%找出距离小于当前节点的节点
         curr_topolopy=curr_topolopy(v4);%更新拓扑相邻集合
         %% ------------------删除curr_topolopy中属于比route(end)离目的节点距离远的结束-----
         if ~isempty(curr_topolopy)%拓扑相邻集合非空就找下
             curr_distance=Dtable(curr_topolopy,number_dem);%获取当前拓扑相邻集合与目的地节点距离集合
             [dis01,index01]=min(curr_distance);%排序
             
             next_node=curr_topolopy(index01(1));
             route=[route next_node];
             distance_s2d=Dtable(number_source,route(end));%重新计算距离
             
         else%如果是空的,进入 模式
             s4=RNG_Ttable(route(end),:);
             v4=find(s4==1);
             if numel(v4)>0
                 s5=randperm(numel(v4));
                 v5=find(s5==1);
                 next_node=v4(v5);
                 route=[route next_node];
                 distance_s2d=Dtable(number_source,route(end));%重新计算距离
             else
                 %% 从倒数第二个路径点的拓扑相邻集合删除当前这节点
                 if length(route)>=2
                     a01=Ttable01(route(end-1)).topolopy;%上一个节点
                     a01(find(a01==curr_node))=[];
                     Ttable01(route(end-1)).topolopy=a01;
                     %% 从当前路径中删除当前路径点
                     route(end)=[];%删掉最后一个
                 else
                     disp('能量耗尽,无法产生路由路径');
                     break;
                 end
             end
         end
         iter_number=iter_number+1;
     end
     disp('route of GPRS')
     route
     %% 更新节点能量
     [k31,k32]=size(route);
     for i=1:k32
         b01=node_down*node_energy;
         node(route(i)).energy=node(route(i)).energy-b01;
     end
     %% 更新拓扑表
     Ttable=topo_table(node,Range,Dtable);
     %% 更新RNG_topology
     % RNG_Ttable=RNG_topology(node,Dtable,Ttable);%这个太慢,因为有多层嵌套循环,计算距离,运算量太大
     RNG_Ttable=RNG_topology_opt(node,RNG_Ttable);
     %绘图
     s='route of GPRS';
     %绘制路由图
     draw_GPRS_route(node,route,Range,s);
     route_length(k1)=length(route);
 end
%% -------------------贪婪算法结束-------------
 route_length
程序结果:


参考文献:
1.改进的GPSR模型及其仿真分析,吴三斌,王小明,杨 涛,付 红














![[ACM学习] 树形dp之换根](https://img-blog.csdnimg.cn/direct/00a4838d79eb45dfb1d2c86e1d79e6f0.png)




