路由选择协议:

  • 内网关选择协议:
  • RIP(routing information protocol)路由信息协议:达到直连的 网络的距离是 1, 非直连的网络,没经过一个路由器,则距离加1。——方法简单,最多只能有15个路由。而且没有考虑带宽,可能选了距离最短但是带宽也最小的路线。
  • OSPF(open shortest path first)开放最短路径优先:Dijsstra的最短路径算法。
  • 外网选择协议:BGP

重点说说OSPF中使用的最短路径算法:

  • 其实就是数据结构与算法里学的Dijstra算法:
    Dijstra算法:计算图中一个点到其他点的最短路径。如下图就是计算从1点 到2,3,4,5,6点的最短路径。

dis ip routing pro ospf 什么意思 ospf dijkstra_权重

图(带权重的图也称为网)可以用一个二维数组来存储:行用来表示出度的结点,列用来表示相应的入度点,值用来表示边上的代价。上面的图可以用下图e进行表示;用∞表示不可到达,对角线值为0,表示不可从自己到自己。

dis ip routing pro ospf 什么意思 ospf dijkstra_最小值_02

我们还可以用一个一维数组dis来标记1到其余各点的初始路径。

dis ip routing pro ospf 什么意思 ospf dijkstra_结点_03

Dijstra算法干的事就是不断更新这个dis数组,使得每个元素表示从1到各个位置的最小值。

算法如下(以计算结点1到各个位置最短路径来讨论):

1. 首先取出二维数组e中的第一行赋值给dis,表示1可以到达的结点和相应的权重,并作为1到各位结点的最短的估计值。

2. 选出到1最近的结点,即为2;那么到2的最近距离就从“估计值”转为了“确定值”;

3. 选出上一个确定值之后,更新dis,表示1到可以到达的其他节点的距离的最短估计值;2的出度为3和4;更新到3和4的权重:

(1) 3:有1——>3 权重为12 和 2——>3 权重为1+9; 取小值:10

(2) 4: 无穷大和1->2->4 权重为4;取小值4

更新完毕后,dis为:

dis ip routing pro ospf 什么意思 ospf dijkstra_最小值_04


4. 接下来,在dis中3,4,5,6中选择最小的结点,即4结点,那么1到4结点的距离估计值也变为了确定值;并对4的出度3,5,6的值进行更新,如下

(1)3: 上一步已经更新为10 和 4——>3 权重为4+4 ;取小值8

(2)5: ∞ 和 4->5 权重为4+13; 取小值17

(3)6: ∞ 和 4——>6 权重为4+15; 取小值19

dis ip routing pro ospf 什么意思 ospf dijkstra_最小值_05


5. 接下来,在dis中3,,5,6,中选择一个最小值;即3结点;那么到3的距离就从估计值变为确定值,对3的出度5 进行更新。

(1)5: 已经更新的17 和 3——> 5 权重为8+5; 取小值13

更新dis如下:

dis ip routing pro ospf 什么意思 ospf dijkstra_权重_06


6. 接下来对5,6中选择一个最小值,即5结点,那么5结点的距离就从估计值变为确定值了,更新5结点的出度6;

(1)6: 上次更新的19和 5->6的13+4; 取小值17

更新dis如下

dis ip routing pro ospf 什么意思 ospf dijkstra_权重_07


7. 最后对剩余的6取最小值,取出度,没有出度,那么将6从估计值变为确定值。最终dis如下,这便是从1顶点到其余各个顶点的最短路径。

dis ip routing pro ospf 什么意思 ospf dijkstra_最小值_08

算法总结:
  1. 每次都从未加入确定集中的结点中选择最小值,作为下一个确定值
  2. 选好确定值后更新每个出度
  3. 重复步骤1和步骤2

算法实现如下

#include<iostream>
#include<vector>
using namespace std;
int inf = 999999;

//网和要计算的开始结点
void Dijkstra(const vector<vector<int>> &vec, int index , vector<int> &dis) {
    dis = vec[index];  //初始化dis数组,把它赋值给要计算的点和对应的出度之间的权重
    vector<bool> used(n, false); //初始化used数组,用来判断是否已经确定
    used[index] = true;//目标结点首选被确定

    //循环m次;每次取出一个结点
    for(int i = 0; i< m; i++) {
        //找到dis矩阵中 未确定的结点中的最小值
            int min = INT_MAX;
            int u; //确定的结点
            for(int j= 0; j<n; j++) {
                if(used[j] == false && dis[j] < min) {
                    min = dis[j];
                    u = j;
                }
            }
            used[u] = true;// 表示j已经被确定
        //更新j的出度和对应的权重值
            for(int k = 0; k< n; k++) {
                if(k!=u && vec[u][k] < inf) {   //找到不等于结点自身的出度并更新
                    if(dis[k] > dis[u] + vec[u][k]) {
                        dis[k] = dis[u] + vec[u][k];
                    }
                }
            }
    }
}


int main() {
    vector<vector<int>> vec = { {0,1,12,inf,inf,inf}, 
                                {inf,0, 9, 3, inf, inf}, 
                                {inf,inf , 0, inf, 5, inf},
                                {inf,inf,4,0,13,15}, 
                                {inf,inf,inf,inf, 0,4}, 
                                {inf, inf, inf, inf,inf, 0}};
    vector<int> dis;
    Dijstra(vec, 0, dis);
    for(auto d:dis) cout<<d<<endl;
    return 0;
}
0 1 8 4 13 17 
999999 999999 0 999999 5 9    //999999 = inf,表示不可到达