在這篇文章中,我們要討論一下關(guān)于圖的知識(shí)點(diǎn):

1.圖的存儲(chǔ)方式——鄰接矩陣存儲(chǔ)和鄰接表存儲(chǔ)

*鄰接矩陣存儲(chǔ)code如下所示

#include <iostream>
 
using namespace std;
 
template <class T>
class Graph
{
protected:
    int n,e;                                     //e是邊數(shù),n是節(jié)點(diǎn)數(shù)
public:
    virtual bool GInsert(int u,int v,T w)=0;   //圖中在節(jié)點(diǎn)u和v之間插入一條權(quán)值為w的邊
    virtual bool GRemove(int u,int v)=0;        //刪除圖中節(jié)點(diǎn)u和v之間的邊
    virtual bool GExist(int u,int v) const=0;    //判斷圖中節(jié)點(diǎn)u和v之間是否存在路徑
};
 
template <class T>
class MGraph:public Graph<T>
{
protected:                          //這里用protected權(quán)限是為了未來可能存在的繼承該MGraph的類可以訪問
    T **a;                          //二維數(shù)組指針指向圖的鄰接矩陣
public:
    MGraph(int mSize);
    ~MGraph();
    bool GInsert(int u,int v,T w);
    bool GRemove(int u,int v);
    bool GExist(int u, int v)const;
};
template <class T>
MGraph<T>::MGraph(int mSize)               //鄰接矩陣是n*n的大小,即有n個(gè)節(jié)點(diǎn)
{
    n=mSize;
    a=new T* [n];                   //申請(qǐng)一個(gè)大小為n的T*指針類型數(shù)組空間,每個(gè)空間存儲(chǔ)一個(gè)T指針
    for(int i=0;i<n;i++)            //初始化鄰接矩陣
    {
        a[i]=new T [n];             //i個(gè)數(shù)組空間中的指針a[i]分別指向一段n連續(xù)的T類型數(shù)組空間
            for(int j=0;j<n;j++)
            {
                a[i][j]=-1;          //賦值-1,表明i和j節(jié)點(diǎn)之間沒有邊
            }
            a[i][i]=0;              //節(jié)點(diǎn)無自回路
    }
}
template <class T>
MGraph<T>::~MGraph()
{
    for(int i=0;i<n;i++)
        delete []a[i];
    delete []a;
}
template <class T>
bool MGraph<T>::GInsert(int u, int v, T w)
{
    if(u<0||v<0||u>n-1||v>n-1)
    {
        cout<<"節(jié)點(diǎn)值越界"<<endl;
        return false;
    }
    if(a[u][v]!=-1)
    {
        cout<<"邊已經(jīng)存在"<<endl;
        return false;
    }
    a[u][v]=w;
    e++;
    return true;
}
template <class T>
bool MGraph<T>::GRemove(int u,int v)
{
    if(u<0||v<0||u>n-1||v>n-1)
    {
        cout<<"節(jié)點(diǎn)值越界"<<endl;
        return false;
    }
    if(a[u][v]==-1)
    {
        cout<<"要?jiǎng)h除的邊不存在"<<endl;
        return false;
    }
    a[u][v]==-1;
    e--;
    return true;
}
 
template <class T>
bool MGraph<T>::GExist(int u, int v) const
{
    if(u<0||v<0||u>n-1||v>n-1)
    {
        cout<<"GExit:節(jié)點(diǎn)越界"<<endl;
        return false;
    }
    if(a[u][v]==-1)
    {
        cout<<"GExit:邊不存在"<<endl;
        return false;
    }
    cout<<"GExit:邊存在"<<endl;
    return true;
}
 
 
int main()
{
    MGraph<int> a(4);
    a.GInsert(0,1,1);
    a.GExist(0,2);
    return 0;
}

*鄰接表類似于一個(gè)哈希表,鄰接表存儲(chǔ)方式的圖code如下所示

#include <iostream>
using namespace std;
 
template <class T> class LGraph;
template <class T>
class LNode                 //鄰接表節(jié)點(diǎn)類
{
private:
    int adjVex;             //節(jié)點(diǎn)號(hào)
    T w;                    //邊權(quán)值
    LNode<T> *nextArc;      //節(jié)點(diǎn)指針
public:
    LNode(int vertex,T weight,LNode<T> *next)
    {
        adjVex=vertex;
        w=weight;
        nextArc=next;
    }
 
    friend class LGraph<T>; //友元類LGraph可以訪問類LNode中的private成員
};
 
template <class T>
class LGraph                //鄰接表類
{
private:
    LNode<T> **a;           //鄰接表二維指針
    int n;                  //圖的節(jié)點(diǎn)數(shù)
    int e;                  //圖的邊數(shù)
public:
    LGraph(int mSize);
    ~LGraph();
    bool LExist(int u,int v);
    bool LInsert(int u,int v,T w);
    bool LRemove(int u,int v);
};
 
template<class T>
LGraph<T>::LGraph(int mSize)    //初始化鄰接表
{
    n=mSize;
    a=new LNode<T>* [n];
    for(int i=0;i<n;i++)
    {
        a[i]=NULL;
    }
}
 
template<class T>
LGraph<T>::~LGraph()
{
    for(int i=0;i<n;i++)
    {
        delete [] a[i];
    }
    delete []a;
}
 
template<class T>
bool LGraph<T>::LExist(int u,int v)
{
    if(u<0||v<0||u>n-1||v>n-1)
    {
        cout<<"LExist:節(jié)點(diǎn)號(hào)越界"<<'\n';
        return false;
    }
    LNode<T> *p=a[u];
    while(p)
    {
        if(p->adjVex==v)
        {
            cout<<"LExist:存在"<<u<<"-"<<v<<"邊"<<'\n';
            return true;
        }
        p=p->nextArc;
    }
    if(!p)
        return false;
}
 
template<class T>
bool LGraph<T>::LInsert(int u,int v,T w)
{
    if(u<0||v<0||u>n-1||v>n-1)
    {
        cout<<"LInsert:節(jié)點(diǎn)號(hào)越界"<<'\n';
        return false;
    }
    if(LExist(u,v))
    {
        cout<<"LInsert:已經(jīng)存在"<<u<<"-"<<v<<"邊"<<'\n';
        return false;
    }
    LNode<T> *p=new LNode<T>(v,w,a[u]);
    a[u]=p;
    e++;
    return true;
}
 
template<class T>
bool LGraph<T>::LRemove(int u,int v)
{
    if(u<0||v<0||u>n-1||v>n-1)
    {
        cout<<"LRemove:節(jié)點(diǎn)號(hào)越界"<<'\n';
        return false;
    }
    if(!LExist(u,v))
    {
        cout<<"LRemove:不存在"<<u<<"-"<<v<<"邊"<<'\n';
        return false;
    }
    LNode<T> *p=a[u],*q=NULL;
    while(p&&p->adjVex!=v)
    {
        q=p;
        p=p->nextArc;
    }
    if(!p)
        return false;
    if(q)
        q->nextArc=p->nextArc;
    else
        a[u]=p->nextArc;
    delete p;
    e--;
    return true;
}

2.圖的深度優(yōu)先遍歷(DFS),這里我們討論以鄰接表形式存儲(chǔ)的圖如何進(jìn)行深度優(yōu)先遍歷。這里采用了遞歸法,大致思路如下

(1)訪問任意節(jié)點(diǎn)v,并對(duì)v打上已經(jīng)訪問過的標(biāo)記

(2)依次從v的未訪問鄰接點(diǎn)出發(fā),深度優(yōu)先搜索圖

#include "lgraph.cpp"
 
//圖的搜索
template <class T>
class ExtLGraph:public LGraph<T>
{
private:
    void DFS(int v,bool *visited);          //從v節(jié)點(diǎn)出發(fā)深度優(yōu)先搜索,visited是標(biāo)志位數(shù)組指針
    //void BFS();
public:
    ExtLGraph(int mSize):LGraph<T>(mSize){} //調(diào)用父類的構(gòu)造函數(shù)來初始化子類構(gòu)造函數(shù)
    void DFS();                             //深度優(yōu)先遍歷
    //void BFS();                               //寬度優(yōu)先遍歷
};
template <class T>
void ExtLGraph<T>::DFS()
{
    bool *visited=new bool [n];             //創(chuàng)建標(biāo)志位數(shù)組
    for(int i=0;i<n;i++)
        visited[i]=false;                   //所有標(biāo)志位至false,表明未訪問過
    for(int i=0;i<n;i++)
        if(!visited[i])                     //未訪問過的節(jié)點(diǎn)進(jìn)行深度優(yōu)先搜索遞歸算法
            DFS(i,visited);
    delete [] visited;
}
template <class T>
void ExtLGraph<T>::DFS(int v,bool *visited)
{
    visited[v]=true;                        //v節(jié)點(diǎn)標(biāo)志位至為true
    cout<<" "<<v;                           //打印輸出訪問到的節(jié)點(diǎn)v
    LNode<T> *p=a[v];
    while(p)
    {
        if(!visited[p->adjVex])
            DFS(p->adjVex,visited);
        p=p->nextArc;
    }
    
}

注意:由于ExtLGraph類是LGraph的子類,由于友元類無法繼承的原因,在ExtLGraph類中無法訪問LNode類中的private成員,因此LNode類中應(yīng)該將ExtLGraph類設(shè)置為友元類?。?!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • https://zh.visualgo.net/graphds 淺談圖形結(jié)構(gòu)https://zh.visualgo...
    狼之獨(dú)步閱讀 4,417評(píng)論 0 0
  • 1. 圖的定義和基本術(shù)語 線性結(jié)構(gòu)中,元素僅有線性關(guān)系,每個(gè)元素只有一個(gè)直接前驅(qū)和直接后繼;樹形結(jié)構(gòu)中,數(shù)據(jù)元素(...
    yinxmm閱讀 5,656評(píng)論 0 3
  • 圖是一種比線性表和樹更復(fù)雜的數(shù)據(jù)結(jié)構(gòu),在圖中,結(jié)點(diǎn)之間的關(guān)系是任意的,任意兩個(gè)數(shù)據(jù)元素之間都可能相關(guān)。圖是一種多對(duì)...
    Alent閱讀 2,420評(píng)論 1 22
  • 1 概述 圖是數(shù)據(jù)結(jié)構(gòu)中最復(fù)雜的形式,也是最燒腦的結(jié)構(gòu)。無數(shù)的牛人樂此不疲地鉆研,然而,時(shí)至今日,依然有很多問題等...
    CodingTech閱讀 2,536評(píng)論 0 8
  • 我愛你 永恒不熄 我走過你身邊,悄然對(duì)視。從前我只會(huì)知道,那是你告訴我,你不想看見我的訊號(hào)。但從今天來看,我知...
    弗蘭德老鬼閱讀 231評(píng)論 0 6

友情鏈接更多精彩內(nèi)容