Graph(图基础)

图的概念

图是用线或边连接在一起的顶点或节点的集合。
图是顶点集 V V V 和边集 E E E 的有序对 G = ( V , E ) G=(V,E) G=(V,E)

图的分类

根据图的定义一个图不能有重复的边。

  • 无向图(加权无向图)
  • 有向图(加权有向图)

图的存储

图的存储分为:邻接矩阵,邻接链表,邻接数组

邻接矩阵:

部分原代码截取(全代码到GitHub获取)

template<typename T>
class Graph{
    public:
        Graph();
        ~Graph();
        void inital();
        void dfs1(){int x;cin>>x;dfs(x,1);output(1);}
        void bfs1(){int x;cin>>x;bfs(x,1);output(1);}
        void output(int);
    private:
        T** element;
        T* reach;
        void bfs(int,int);
        void dfs(int,int);
        int size;
        const int MAX=1000000;
};

template<typename T>
Graph<T>::Graph(){
    element=NULL;
    reach=NULL;
    size=0;
}

template<typename T>
Graph<T>::~Graph(){
   for(int i=0;i<=size;i++){
       delete [] element[i];
   }
   delete [] element;

   delete [] reach;

    reach=NULL;
    element=NULL;
    size=0;
}

template<typename T>
void Graph<T>::inital(){
    int side_size;
    cin>>size>>side_size;
    element=new T * [size+1];
    for(int i=0;i<=size;i++){
        element[i]=new T [size+1];
    }

    for(int i=1;i<=size;i++)
        for(int j=1;j<=size;j++){
            if(i==j) element[i][j]=0;
            else element[i][j]=MAX;
        }

    reach=new T [size+1];
    for(int i=0;i<=size;i++){
        reach[i]=MAX;
    }
    

    while(side_size--){
        int x,y;
        T w;
        cin>>x>>y>>w;
        //all the side is different
        element[x][y]=w;
        element[y][x]=w;
    }
}

邻接链表:
其中的每个链表完全是自己维护的,也可以通过list(STL)维护链表(具体代码详见GitHub)

class Node{
    public:
        int index;
        int weight;
        Node * next;

        Node(){index=0;weight=0;next=NULL;}
        Node(int x,int y,Node * ne){
            index=x;
            weight=y;
            next=ne;
        }
};

template<typename T>
class Graph{
    public:
        Graph();
        ~Graph();
        void inital();
//        void dfs1(){int x;cin>>x;dfs(x,1);output(1);}
//        void bfs1(){int x;cin>>x;bfs(x,1);output(1);}
//        void output(int);
    private:
        Node** element;
        T* reach;
//        void bfs(int,int);
//        void dfs(int,int);
        int size;
        const int MAX=1000000;
};

template<typename T>
Graph<T>::Graph(){
    element=NULL;
    reach=NULL;
    size=0;
}

template<typename T>
Graph<T>::~Graph(){
   for(int i=0;i<=size;i++){
       Node* cur=element[i];
       while(cur!=NULL){
           Node* record=cur->next;
           delete cur;
           cur=record;
       }
   }  

   delete [] element;
   delete [] reach;

    reach=NULL;
    element=NULL;

}

template<typename T>
void Graph<T>::inital(){
    int side_size;
    cin>>size>>side_size;
    
    element=new Node* [size+1];
    //inital all the element point to NULL
    for(int i=0;i<=size;i++){
        element[i]=NULL;
    }

    reach=new T [size+1];
    for(int i=0;i<=size;i++){
        reach[i]=MAX;
    }
    

    while(side_size--){
        int x,y;
        T w;
        cin>>x>>y>>w;
        //add to list   
        Node* cur_new=new Node (y,w,element[x]);
        element[x]=cur_new;

        cur_new=new Node (x,w,element[y]);
        element[y]=cur_new;
    }
}

图的遍历

(此处的代码都是通过邻接矩阵存储的图,其他方法详见GitHub)

  1. 深度优先搜索
    具体算法
    • 首先从一个点开始,寻找连接与它的所有边,找到一条后,通过该条边找到另一个点,此时从找到的另一个点开始,继续搜索它邻接的边。
    • 直到找不到邻接的边,就回溯到它的父亲节点(即从哪个点找到该点),继续搜索父亲节点邻接与的边。直到找完。
template<typename T>
void Graph<T>::dfs(int x,int label){

    for(int i=1;i<=size;i++){
        if(reach[i]!=label&&element[x][i]!=MAX){
            reach[i]=label;
            dfs(i,label);   //find the next ,and mark the node with label
        }
    }
}
  1. 广度优先搜索
    1. 从一个点开始,将于该点联通的所有点加入队列中。
    2. 当第一个点的所有邻接点都找完之后,在开始下一层点的搜索。
    3. 直到队列中不存在元素终止。
template<typename T>
void Graph<T>::bfs(int x,int label){
   
    queue<int> que;
    //add the start to queue.
    que.push(x);
    reach[x]=label;

    while(!que.empty()){
        int cur=que.front();
        que.pop();

        for(int i=1;i<=size;i++){
            if(element[cur][i]!=MAX&&reach[i]!=label){  //add to queue
                que.push(i);
                reach[i]=label;
            }
        }
    }
}

源代码GitHub GitHub

下一篇:图的应用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值