zoukankan      html  css  js  c++  java
  • 数据结构与算法之“图”

      其实所有的数据结构都是“图”。图其实就是一系列的顶点和边的集合。如果边有指向性就叫做有向图,否则就是无向图,边也可以有权值。任意两点间都有路径连接的图叫做连通图,顶点连接的边数叫做这个顶点的度。

      没有圈的连通图就是所谓的树,没有圈的非连通图就是森林。

    1、图的表示

      (1)邻接矩阵

      使用|V|*|V|的二维数组来表示:graph[V][V]。graph[i][j]表示顶点i和顶点j的关系,在无权图中,graph[i][j]=1表示i,j之间有边,=0表示无边。无向图中,这是一个堆成矩阵;若是带权图,则graph[i][j]表示顶点i到顶点j的边的权值,无边时graph[i][j]=INF。

      用邻接矩阵可以在o(1)时间内判断两点间是否有边存在,可是代价是花费o(|V|2)的空间。在无向图中由于是对称矩阵,至少浪费了一般的空间;当一个图的边很少时,空间利用率更低。

      (2)邻接表

      每个顶点都有一个邻接表(包含邻接于该顶点的所有顶点)。邻接表只需要占用o(|V|+|E|)的空间,极大地提高了空间的利用率。邻接表也有两种表示方式,用链表来表示,则为邻接链表;用数组表示,则为邻接数组。无论是邻接链表还是邻接数组,它们的空间复杂度都渐近相等,但在图的很多算法中,邻接数组的用时比邻接矩阵要少。

      这里采用的是邻接表的表示方法:

    vector<int> G[MAX_V];//MAX_V为顶点数

      其中,G[i]表示顶点i的邻接表。  

      判断边(i,j)是否存在于图G中:

    bool existsEdge(int i,int j){
        vector<int>::iterator it;
        for(it=G[i].begin(); it!=G[i].end(); it++)
            if(j == *it)
                return true;
        return false;
    }

      向G中插入边(i,j):

    void insertEdge(int i,int j){
        if(existsEdge(i,j))
            return ;
        G[i].push_back(j);
        G[j].push_back(i);
    }

      从G中删除边(i,j):

    void eraseEdge(int i,int j){
        for(it=G[i].begin(); it!=G[i].end(); it++)
            if(j == *it)
                G[i].erase(it);
        for(it=G[j].begin(); it!=G[j].end(); it++)
            if(i == *it)
                G[j].erase(it);
    }

      顶点i的度:

    int degree(int i){
        return G[i].size();
    }

    2、图的遍历

      其中,flag数组用来记录已经搜索过的顶点。这里的G[MAX_V]为无向图,通过遍历打印出所有的边。

      (1)深度优先遍历(DFS)

      从一个顶点v开始,选择一个邻接于v并且未到达的顶点u,如果u存在,则从u开始新的DFS,否则,u存在,结束搜索返回。

    void dfs(int v){
        static int flag[MAX_V] = {0};
        flag[v] = 1;
        for(int i=0; i<G[v].size(); i++){
            if(0 == flag[G[v][i]]){
                dfs(G[v][i]);
                printf("%d <--> %d
    ",v,G[v][i]);
            }
        }
    }

      (2)广度优先遍历(BFS)

      其实BFS就跟树的层序遍历一样,从一个顶点开始,访问它的所有邻接顶点,并把访问过的邻接顶点放入队列里,每次访问完所有的邻接顶点后,就从队列里取出一个顶点,然后,继续前面操作,直到队列里的元素个数为0。

    void bfs(int v){
        queue<int> que;
        bool flag[MAX_V];
        fill(flag,flag+MAX_V,false);
        que.push(v);
        flag[v] = true;
        while(!que.empty()){
            int vi = que.front();
            que.pop();
            vector<int> it;
            for(it=G[vi].begin(); it!=G[vi].end(); it++){
                if(!flag[*it]){
                    printf("%d <--> %d
    ",vi,*it);
                    que.push(*it);
                    flag[*it] = true;
                }
            }
        }
    }

      图作为最高级的一种数据结构,所有适用于图的算法,都可以适用于树,线性表。DFS和BFS是图中最常用的两个算法,很多其他图的算法包括最小生成树,最短路径算法,都是用的DFS和BFS的思想。

      代码详见:https://github.com/whc2uestc/DataStructure-Algorithm/tree/master/graph

  • 相关阅读:
    重视需求
    某2个人的qq对话
    公司安全提示
    需求实施心得
    项目远景
    发布系统应注意的几小点问题
    把握项目开发的节奏
    Css介绍
    调研工作的思路
    网,无处不在
  • 原文地址:https://www.cnblogs.com/whc-uestc/p/4662457.html
Copyright © 2011-2022 走看看