圖的鄰接多重表和搜索(C++版本)

最近在學數據結構,學到圖這一章,網上的C++版本的代碼亂得不行,所以自己寫了一個完整C++版本的放這裏。

用鄰接多重表表示一個無向圖,並給出DFS和BFS搜索代碼。鄰接多重表好處就是賊直觀,幾條邊就幾個邊表的元素。

代碼如下:

邊表節點定義(其實就是邊的定義)

typedef struct EdgeNode          //鄰接多重表
{
    int iVertex;
    EdgeNode* iLink;
    int jVertex;
    EdgeNode* jLink;

};

 頂點表節點的定義

template <typename Type>
struct VextexNode             //鄰接多重表的頂點表
{
    Type Data;
    EdgeNode* TailLink;
    Mark Flag;
};

最後是圖的模板類

#ifndef MULADJACENCYLIST_H
#define MULADJACENCYLIST_H
#include "SideNode.h"
#include "VexNode.h"
#include <iostream>
#include <vector>
#include <list>
#include <set>
using namespace std;

template <typename Type, int N>
class MulAdjacencyList
{
public:
    MulAdjacencyList();
    ~MulAdjacencyList();
    void AddEdge();
    int DeleteEdge(int x, int y);
    void DFS(int x, const Type& Value);
    void BFS(int x, const Type& Value);  
private:
    int InitEdgeNum();    //構造函數中先輸入圖的邊數
    int NextIndex(int CurIndex);     //查找最近的一個鄰接點,CurIndex爲點的下標而不是值
    void BFSHelper(set <int> SourceList, const Type& Value); //BFS真正的遞歸函數
    void AllNextIndex(int i);     //和i相連的所有鄰接點,i爲點的下標而不是值
    VextexNode <Type> VertexArray[N];   //頂點表
    EdgeNode* LastPtr(int x);  
    int EdgeNums;  //當前的邊數
    vector <int> Temp;   //用來存放搜索結果的容器
    set <int> TempList; //用來存放AllNextIndex結果的容器
};

template <typename Type, int N>
void MulAdjacencyList<Type, N>::AddEdge()  //添加一條x到y的無向邊
{
    cout << "Enter the edge wanna insert!" << endl;
    int i, j;
    if (cin >> i >> j)
    {
        EdgeNode* TarPtr = new EdgeNode;
        TarPtr->iVertex = i;
        TarPtr->jVertex = j;
        TarPtr->iLink = VertexArray[i].TailLink;
        TarPtr->jLink = VertexArray[j].TailLink;
        VertexArray[i].TailLink = TarPtr;
        VertexArray[j].TailLink = TarPtr;
        EdgeNums++;
    }
    else
        cin.clear();
}

template <typename Type, int N>
int MulAdjacencyList<Type, N>::InitEdgeNum()
{
    cout << "Enter the quantity of edges!"<< endl;
    cin >> EdgeNums;
    return EdgeNums;
}

template <typename Type, int N>
EdgeNode* MulAdjacencyList<Type, N>::LastPtr(int x)   //找到和x相關的最後一條邊
{
    EdgeNode* Temp = VertexArray[x].TailLink;
    EdgeNode* LastTemp = Temp;
    while (Temp != NULL)
    {
        if (Temp->iVertex == x)
        {
            LastTemp = Temp;
            Temp = Temp->iLink;
        }
        else if (Temp->jVertex == x)
        {
            LastTemp = Temp;
            Temp = Temp->jLink;
        }
    }
    return LastTemp;
}

template <typename Type, int N>
MulAdjacencyList <Type, N>::MulAdjacencyList()
{
    cout << "enter the vertex for the graph!" << endl;
    for (int i = 0; i != N; ++i)
    {
        cin >> VertexArray[i].Data;
        VertexArray[i].TailLink = NULL;
        VertexArray[i].Flag = No;
    }
    int Temp = InitEdgeNum();    
    for (int i = 0; i != Temp; ++ i)
        AddEdge();
}

template <typename Type, int N>
int MulAdjacencyList<Type, N>::DeleteEdge(int x, int y)   //刪除x到y的一條無向邊  
{    
    if (x == y)return 0;
    EdgeNode* Q = VertexArray[x].TailLink; //Q的下一條邊就是要刪除的邊
    EdgeNode* P = VertexArray[x].TailLink;   //先從x出發找到要刪除的邊,調整完x的邊的次序,得到指針,最後再刪除
    if (P && P->jVertex == y)    //假如第一條邊就是待刪除的邊, P是前向判斷,避免P爲NULL的情況下還執行P->jVertex
        VertexArray[x].TailLink = P->iLink;
    else if (P && P->iVertex == y)
        VertexArray[x].TailLink = P->jLink;
    else             //假如第一條邊不是要刪除的邊,則向下查找
    {
        while (P)
        {
            if (P->iVertex == x && P->jVertex != y)//不是要刪除的邊
            {
                Q = P;
                P = P->iLink;
            }
            else if (P->jVertex == x && P->iVertex != y)
            {
                Q = P;
                P = P->jLink;
            }
            else         //找到了鄰接點y
                break;
        }
        if (P == NULL)
        {
            return 0;             //這裏可以加入一句警告“Not Found”
        }
        else if (P->iVertex == x && P->jVertex == y)  //找到了邊(x,y),調整x的邊的次序
        {
            if (Q->iVertex == x)
                Q->iLink = P->iLink;
            else
                Q->jLink = P->iLink;
        }
        else if (P->iVertex == y && P->jVertex == x)
        {
            if (Q->iVertex == x)
                Q->iLink = P->jLink;
            else
                Q->jLink = P->jLink;
        }
    }

    P = VertexArray[y].TailLink;   //從y出發開始查找,調整y的邊的次序
    if (P && P->iVertex == x)
        VertexArray[y].TailLink = P->jLink;
    else if (P && P->jVertex == x)
        VertexArray[y].TailLink = P->iLink;
    else
    {
        while (P != NULL)
        {
            if (P->iVertex == y && P->jVertex != x)
            {
                Q = P;
                P = P->iLink;
            }
            else if (P->jVertex == y && P->iVertex != x)
            {
                Q = P;
                P = P->jLink;
            }
            else
                break;
        }
        if (P == NULL) //由於上面打了一次警告,這裏就不打警告了
            return 0;
        else if (P->iVertex == y && P->jVertex == x)
        {
            if (Q->iVertex == y)
                Q->iLink = P->iLink;
            else
                Q->jLink = P->iLink;
        }
        else if ((P->jVertex == y && P->iVertex == x))
        {
            if (Q->iVertex == y)
                Q->iLink = P->jLink;
            else
                Q->jLink = P->jLink;
        }
    }
    cout << x << endl << y << endl<<"yici"<<endl;
    if (P != NULL) delete P;            //調整完線序了,刪掉邊
    --EdgeNums;
    return 1;
}

template <typename Type, int N>
MulAdjacencyList <Type, N>::~MulAdjacencyList()
{
    for (int i = 0; i != N; ++i)
    {
        for (int j = 0; j != N; ++j)
            DeleteEdge(i,j);
    }
}

template <typename Type, int N>
void MulAdjacencyList <Type, N>::AllNextIndex(int i)   //找到和i相關聯的所有的點
{
    EdgeNode* Ptr = VertexArray[i].TailLink;
    while (Ptr != NULL)
    {
        if (Ptr->iVertex == i)
        {
            if (VertexArray[Ptr->jVertex].Flag != Yes)TempList.insert(Ptr->jVertex);
            Ptr = Ptr->iLink;
        }
        else
        {
            if (VertexArray[Ptr->iVertex].Flag != Yes)TempList.insert(Ptr->iVertex);
            Ptr = Ptr->jLink;
        }
    }
}

template <typename Type, int N>
int MulAdjacencyList <Type, N>::NextIndex(int CurIndex)
{
    EdgeNode* Ptr = VertexArray[CurIndex].TailLink;
    while (Ptr != NULL)
    {
        if (Ptr->iVertex == CurIndex)
        {
            if (VertexArray[Ptr->jVertex].Flag == No){
                return Ptr->jVertex;
            }
            else
                Ptr = Ptr->iLink;
        }
        else if (Ptr ->jVertex == CurIndex)
        {
            if (VertexArray[Ptr->iVertex].Flag == No){
                return Ptr->iVertex;
            }
            else
                Ptr = Ptr->jLink;
        }
    }
    if (Ptr == NULL) { return N; }
}

template <typename Type, int N>
void MulAdjacencyList <Type, N>::DFS(int x, const Type& Value)  //x爲起始的下標,Value爲查找的值
{
    if (VertexArray[x].Data == Value)
    {
        Temp.push_back(x);
    }
    VertexArray[x].Flag = Yes;
    int TempIndex = NextIndex(x);
    while (TempIndex != N)
    {
        DFS(TempIndex, Value);
        TempIndex = NextIndex(x);
    }
    for (vector <int>::const_iterator i = A.Temp.begin(); i != A.Temp.end(); ++i)  //打印找到的元素
        cout << *i << endl;
}

template <typename Type, int N>
void MulAdjacencyList <Type, N>::BFSHelper(set <int> SourceList,const Type& Value)
{
    if (!SourceList.empty())
    {
        for (set <int>::const_iterator i = SourceList.begin(); i != SourceList.end(); ++i)
        {
            VertexArray[*i].Flag = Yes;
            if (VertexArray[*i].Data == Value)
                Temp.push_back(*i);
        }
        for (set <int>::const_iterator i = SourceList.begin(); i != SourceList.end(); ++i)
        {
            AllNextIndex(*i);
        }
        SourceList = TempList;
        TempList.clear();
        BFSHelper(SourceList, Value);
    }
}

template <typename Type, int N>
void MulAdjacencyList <Type, N>::BFS(int x, const Type& Value)
{
    set <int> Set;
    Set.insert(x);
    BFSHelper(Set, Value);
}
#endif

 大類的代碼有點亂,先挖個坑以後有空再來填上,希望對各位和自己有幫助。

發佈了38 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章