27、图算法-最短路径应用(路由表)、旅行商问题

1、路由表
路由:将数据从一个点传输到另一个点(中间会有很多其他点)的决策过程。
网关:节点,负责传播数据段或数据包
路由表:存储互联网的结构信息或拓扑信息,它为每个路由器如何到达网关存储一个条目
SPF路由:最短路径路由,每个路由器都维护有自己的网路图,以便计算自身与其他节点之间的最短路径来更新其路由表。

//paths最短路径生成的数,每个节点包含d 和父节点信息;destination:目的节点 
//paths是头结点到所有节点的最短路径
 int route(LIST_ATTRITIVE *paths, PathVertex *destination, PathVertex **next, int (*match)(const void *key1, const void *key2))
{
    PathVertex *temp, *parent;
    LIST_ELEMENT *element;
    int found = 0;

    //找到目的节点 
    for(element = list_head(paths); element != NULL; element = list_next(element))
    {
        if(match(list_data(element), destination))
        {
            temp = list_data(element);
            parent = ((PathVertex *)list_data(element))->parent;
            found = 1;
            break;
        }
    }
    if(!found)
        return -1;

    //从目的节点开始一层一层找父节点   
    while(parent != NULL)
    {
        temp = list_data(element);
        found = 0;

        //每次找一个父节点 
        for(element = list_head(paths); element != NULL; element = list_next(element))
        {
            if(match(list_data(element), parent))
            {
                parent = ((PathVertex *)list_data(element))->parent;
                found = 1;
                break;
            }
        }
        if(!found)
            return -1;

    } 
    //最后parent = NULL,它的前一个节点为头结点在temp中 
    //最后temp/next中为头结点 ,如果在while中把每次找到的点放在一个数组中就是一个路径 
    *next = temp;

    return 0; 
}

2、旅行商问题,这是一个NP完全问题
每个地方访问一次,最终返回起点,尽可能短的路径。这个访问轨迹称为哈密顿圈。

最近邻点法:一种近似计算旅行商问题的方法。它类似于广度优先搜索法,往图更深一层搜索前,它需要扫描与路线中最后顶点相连的所有点。也应用了贪心算法,每次将一个顶点加入路线时,它选择当前最优的顶点。可是,在一个节点加入当前最邻近的点可能会给接下来的路线带来负面影响。

最近邻点法并不是最优算法,长度通常是最优算法的两倍。
27、图算法-最短路径应用(路由表)、旅行商问题_第1张图片

//x,y中保存节点的坐标,方便计算点与点之间的距离
typedef struct TspVertex
{
    void *data;
    double x, y;
    VertexColor color;

}TspVertex;


//vertices:所有节点; tour:生成的路线,头和尾都是start形成回路 
int tsp(LIST_ATTRITIVE *vertices, const TspVertex *start, LIST_ATTRITIVE *tour, int (*match)(const void *key1, const void *key2))
{
    TspVertex *tsp_vertex, *tsp_start, *selection;
    LIST_ELEMENT *element;
    double minimum, distance, x, y;
    int found, i;

    list_init(tour, NULL);
    found = 0;

    //找到头节点,涂黑加入路径,一个一个按顺序加入路径 
    for(element = list_head(vertices); element != NULL; element = list_next(element))
    {
        tsp_vertex = list_data(element);
        if(match(tsp_vertex, start))
        { 
            list_ins_next(tour, list_tail(tour), tsp_vertex);

            tsp_start = tsp_vertex;
            tsp_vertex->color = black;
            found = 1;

            x = tsp_vertex->x;
            y = tsp_vertex->y;
        } 
        else
        {
            tsp_vertex->color = white;
        } 
    }

    if(!found)
        return -1;

    i = 0;

    //每次找到一个最近的点,涂黑 
    while(i < list_size(vertices) - 1)
    {
        minimum = DBL_MAX; 

        //找白色节点中最近的点 
        for(element = list_head(vertices); element != NULL; element = list_next(element))
        {
            tsp_vertex = list_data(element);
            if(tsp_vertex->color == white)
            {
                distance = sqrt(pow(tsp_vertex->x - x, 2.0) + pow(tsp_vertex->y - y, 2.0));

                if(distance < minimum)
                {
                    minimum = distance;
                    selection = tsp_vertex;
                } 
            }
        }

        x = selection->x;
        y = selection->y;
        selection->color = black;

        //每次插入一个点 
        if(list_ins_next(tour, list_tail(tour), selection) != 0)
        {
            list_destory(tour);
            return -1;
        }
        i++;    
    }

    //最好再插入头结点,形成回路 
    if(list_ins_next(tour, list_tail(tour), tsp_start) != 0)
    {
        list_destory(tour);
        return -1;
    }
    return 0;
}

你可能感兴趣的:(笔记-算法精解C语言实现)