分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_从零开始学习数据结构>图的遍历...

图的存储结构:邻接矩阵、邻接表,那么对于不同的存储结构必然存在着不同的访问方式,拿到具体数据的过程就是图的遍历。

1、遍历

图的遍历与树的很相似,遍历满足:

(1)、对每一个顶点都得进行一次访问;

(2)、对其不能进行重复的访问,只能是一次;

对上次的一个补充: 当父类是模板类时,子类继承后,要是想调用父类的方法/数据,必须加上模板的作用域限定符,例 : Grapth::maxVertices;方可在子类中使用父类的数据或方法。

2、深度优先(DFS)

DFS(depth first search):一个不断探查和回溯的过程,一个往死里整的过程;一条路必须走到死方可结束;

模型分析:

f15328ba9a1ded95c3e79ba51caa06c7.png

3、广度优先(BFS)

BFS(breadth first search):一个逐层遍历的过程,借助队列来实现 !

模型分析:

3e1a04a09121dad3b7155be7df9de617.png

4、代码实现

(1)、对无向图的遍历,用邻接矩阵实现DFS;

借助了一个visit数组,看当前顶点是否被访问过,visit数组充当标志!

 1public:
2    void DFS(const Type &v){
3        int n = Graph::getCurVertex(); 4        bool *visit = new bool[n]; 5 6        for(int i = 0; i  7            visit[i] = false; 8        } 9        DFS(v, visit);10        delete []visit;11    }12protected:13    void DFS(const Type &v, bool *visit){14        cout<"-->";15        int index = getVertexIndex(v);16        visit[index] = true;17        int w = getFirstNeighbor(v);18        while(w != -1){19            if(!visit[w]){20                DFS(getValue(w), visit);21            }22            w = getNextNeighbor(v, getValue(w)); 23        }24    }

(2)、对无向图的遍历,用邻接矩阵实现BFS;

借助visit数组和队列来实现;

 1void BFS(const Type &v){
2    int n = Graph::getCurVertex(); 3    bool *visit = new bool[n]; 4    for(int i = 0; i  5        visit[i] = false; 6    } 7    cout<"-->"; 8    int index = getVertexIndex(v); 9    visit[index] = true;1011    queue<int> q;  //队列中存放的是顶点下标;12    q.push(index);13    int w;14    while(!q.empty()){15        index = q.front();16        q.pop();17        w = getFirstNeighbor(getValue(index));18        while(w != -1){19            if(!visit[w]){20                cout<"-->";21                visit[w] = true; 22                q.push(w);23            }2425            w = getNextNeighbor(getValue(index), getValue(w));2627        }28    }2930    delete []visit;31}

5、完整代码、测试代码、测试结果

(1)、完整代码 (无向图)

  1#ifndef _GRAPH_H_
2#define _GRAPH_H_
3
4#include
5#include
6using namespace std;
7
8#define VERTEX_DEFAULT_SIZE        10
9
10template<typename Type>    
11class Graph{
12public:
13    bool isEmpty()const{
14        return curVertices == 0;
15    }
16    bool isFull()const{
17        if(curVertices >= maxVertices || curEdges >= curVertices*(curVertices-1)/2)
18            return true;  //图满有2种情况:(1)、当前顶点数超过了最大顶点数,存放顶点的空间已满
19        return false;     //(2)、当前顶点数并没有满,但是当前顶点所能达到的边数已满
20    }
21    int getCurVertex()const{
22        return curVertices;
23    }
24    int getCurEdge()const{
25        return curEdges;
26    }
27public:
28    virtual bool insertVertex(const Type &v) = 0;  //插入顶点
29    virtual bool insertEdge(const Type &v1, const Type &v2) = 0; //插入边
30    virtual bool removeVertex(const Type &v) = 0;  //删除顶点
31    virtual bool removeEdge(const Type &v1, const Type &v2) = 0; //删除边
32    virtual int getFirstNeighbor(const Type &v) = 0; //得到第一个相邻顶点
33    virtual int getNextNeighbor(const Type &v, const Type &w) = 0; //得到下一个相邻顶点
34public:
35    virtual int getVertexIndex(const Type &v)const = 0; //得到顶点下标
36    virtual void showGraph()const = 0;  //显示图
37    virtual Type getValue(int index)const = 0; 
38public:
39    virtual void DFS(const Type &v) = 0; //深度优先
40    virtual void BFS(const Type &v) = 0; //广度优先
41protected:
42    int maxVertices;  //最大顶点数
43    int curVertices;  //当前顶点数
44    int curEdges;  //当前边数
45};
46
47template<typename Type>
48class GraphMtx : public Graph{ //邻接矩阵继承父类矩阵 49#define maxVertices  Graph::maxVertices  //因为是模板,所以用父类的数据或方法都得加上作用域限定符 50#define curVertices  Graph::curVertices 51#define curEdges     Graph::curEdges 52public: 53    GraphMtx(int vertexSize = VERTEX_DEFAULT_SIZE){  //初始化邻接矩阵 54        maxVertices = vertexSize > VERTEX_DEFAULT_SIZE ? vertexSize : VERTEX_DEFAULT_SIZE; 55        vertexList = new Type[maxVertices]; //申请顶点空间 56        for(int i = 0; i //都初始化为0 57            vertexList[i] = 0; 58        } 59        edge = new int*[maxVertices];  //申请边的行 60        for(i = 0; i //申请列空间 61            edge[i] = new int[maxVertices]; 62        } 63        for(i = 0; i //赋初值为0  64            for(int j = 0; j  65                edge[i][j] = 0; 66            } 67        } 68        curVertices = curEdges = 0; //当前顶点和当前边数 69    } 70    GraphMtx(Type (*mt)[4], int sz){  //通过已有矩阵的初始化 71        int e = 0; //统计边数 72        maxVertices = sz > VERTEX_DEFAULT_SIZE ? sz : VERTEX_DEFAULT_SIZE; 73        vertexList = new Type[maxVertices]; //申请顶点空间 74        for(int i = 0; i //都初始化为0 75            vertexList[i] = 0; 76        } 77        edge = new int*[maxVertices];  //申请边的行 78        for(i = 0; i //申请列空间 79            edge[i] = new Type[maxVertices]; 80        } 81        for(i = 0; i //赋初值为矩阵当中的值 82            for(int j = 0; j  83                edge[i][j] = mt[i][j]; 84                if(edge[i][j] != 0){ 85                    e++; //统计列的边数 86                } 87            } 88        } 89        curVertices = sz; 90        curEdges = e/2; 91    } 92    ~GraphMtx(){} 93public: 94    bool insertVertex(const Type &v){ 95        if(curVertices >= maxVertices){ 96            return false; 97        } 98        vertexList[curVertices++] = v; 99        return true;100    }101    bool insertEdge(const Type &v1, const Type &v2){102        int maxEdges = curVertices*(curVertices-1)/2;103        if(curEdges >= maxEdges){104            return false;105        }106107        int v = getVertexIndex(v1);108        int w = getVertexIndex(v2);109110        if(v==-1 || w==-1){111            cout<<"edge no exit"<<endl; //要插入的顶点不存在,无法插入112            return false;113        }114        if(edge[v][w] != 0){  //当前边已经存在,不能进行插入115            return false;116        }117118        edge[v][w] = edge[w][v] = 1; //因为是无向图,对称的,存在边赋为1;119        return true; 120    }  //删除顶点的高效方法121    bool removeVertex(const Type &v){122        int i = getVertexIndex(v);123        if(i == -1){124            return false;125        }126        vertexList[i] = vertexList[curVertices-1];127        int edgeCount = 0;128        for(int k = 0; k 129            if(edge[i][k] != 0){  //统计删除那行的边数130                edgeCount++;131            }132        }133        //删除行134        for(int j = 0; j 135            edge[i][j] = edge[curVertices-1][j];136        }137        //删除列138        for(j = 0; j 139            edge[j][i] = edge[j][curVertices-1];140        }141        curVertices--;142        curEdges -= edgeCount;143        return true;144    }145/*  //删除顶点用的是数组一个一个移动的方法,效率太低。146    bool removeVertex(const Type &v){147        int i = getVertexIndex(v);148        if(i == -1){149            return false;150        }151        for(int k = i; k 152            vertexList[k] = vertexList[k+1];153        }154155        int edgeCount = 0;156        for(int j = 0; j 157            if(edge[i][j] != 0)158                edgeCount++;159        }160161        for(int k = i; k 162        {163            for(int j = 0; j 164            {165                edge[k][j] = edge[k+1][j];166            }167        }168169        for(int k = i; k 170        {171            for(int j = 0; j 172            {173                edge[j][k] = edge[j][k+1];174            }175        }176177        curVertices--;178        curEdges -= edgeCount;179180        return true;181    }        182*/183    bool removeEdge(const Type &v1, const Type &v2){184        int v = getVertexIndex(v1);185        int w = getVertexIndex(v2);186187        if(v==-1 || w==-1){  //判断要删除的边是否在当前顶点内188            return false;  //顶点不存在189        }190        if(edge[v][w] == 0){ //这个边根本不存在,没有必要删191            return false;192        }193        edge[v][w] = edge[w][v] = 0; //删除这个边赋值为0,代表不存在;194        curEdges--;195196        return true;197    }198    int getFirstNeighbor(const Type &v){199        int i = getVertexIndex(v);200        if(i == -1){201            return -1;202        }203        for(int col = 0; col 204            if(edge[i][col] != 0){205                return col;206            }207        }208        return -1;209    }210    int getNextNeighbor(const Type &v, const Type &w){211        int i = getVertexIndex(v);212        int j = getVertexIndex(w);213214        if(i==-1 || j==-1){215            return -1;216        }217        for(int col = j+1; col 218            if(edge[i][col] != 0){219                return col;220            }221        }222223        return -1;224    }225public:226    void showGraph()const{227        if(curVertices == 0){228            cout<<"Nul Graph"<<endl;229            return;230        }231232        for(int i = 0; i 233            cout<"  "; 234        }235        cout<<endl;236        for(i = 0; i 237            for(int j = 0; j 238                cout<"  ";239            }240            cout<endl;241        }242    }243    int getVertexIndex(const Type &v)const{244        for(int i = 0; i 245            if(vertexList[i] == v){246                return i;247            }248        }249250        return -1;251    }252public:253    Type getValue(int index)const{254        return vertexList[index];255    }256    void DFS(const Type &v){257        int n = Graph::getCurVertex();258        bool *visit = new bool[n];259260        for(int i = 0; i 261            visit[i] = false;262        }263        DFS(v, visit);264        delete []visit;265    }266    void BFS(const Type &v){267        int n = Graph::getCurVertex();268        bool *visit = new bool[n];269        for(int i = 0; i 270            visit[i] = false;271        }272        cout<"-->";273        int index = getVertexIndex(v);274        visit[index] = true;275276        queue<int> q;  //队列中存放的是顶点下标;277        q.push(index);278        int w;279        while(!q.empty()){280            index = q.front();281            q.pop();282            w = getFirstNeighbor(getValue(index));283            while(w != -1){284                if(!visit[w]){285                    cout<"-->";286                    visit[w] = true; 287                    q.push(w);288                }289290                w = getNextNeighbor(getValue(index), getValue(w));291292            }293        }294295        delete []visit;296    }297protected:298    void DFS(const Type &v, bool *visit){299        cout<"-->";300        int index = getVertexIndex(v);301        visit[index] = true;302        int w = getFirstNeighbor(v);303        while(w != -1){304            if(!visit[w]){305                DFS(getValue(w), visit);306            }307            w = getNextNeighbor(v, getValue(w)); 308        }309    }310private:311    Type *vertexList;  //存放顶点的数组312    int **edge;  //存放边关系的矩阵313};314315#endif

(2)、测试代码

 1#include"Graph1.h"
2
3int main(void){
4   GraphMtx<char> gm;
5    gm.insertVertex('A');
6    gm.insertVertex('B');
7    gm.insertVertex('C'); //B的第一个邻接顶点是C,
8    gm.insertVertex('D');
9    gm.insertVertex('E');
10    gm.insertVertex('F');
11    gm.insertVertex('G');
12    gm.insertVertex('H');
13    gm.insertVertex('I');
14
15    gm.insertEdge('A','B');
16    gm.insertEdge('A','C');
17    gm.insertEdge('A','D');
18    gm.insertEdge('B','C');
19    gm.insertEdge('B','E');
20    gm.insertEdge('C','F');
21    gm.insertEdge('D','F');
22    gm.insertEdge('E','G');
23    gm.insertEdge('F','H');
24    gm.insertEdge('H','I');
25
26    gm.showGraph();
27
28    cout<<"------------------------------------------------"<<endl;
29    gm.DFS('A');
30    cout<<"Nul."<<endl;
31    gm.BFS('A');
32     cout<<"Nul."<<endl;
33    return 0;
34
35}

(3)、测试结果

无向图的模型:

f4508fcf2ce80188fc153a095f9f1629.png

8b52459ff56542a0d64ea57e7bb3b1f3.png

推荐阅读:

从零开始学习数据结构-->入门篇 从零开始学习数据结构-->链表 从零开始学习数据结构-->线性表 从零开始学习数据结构-->栈 从零开始学习数据结构-->队列 从零开始学习数据结构-->矩阵+串 从零开始学习数据结构-->哈希表 从零开始学习数据结构-->散列桶 从零开始学习数据结构-->二叉树

从零开始学习数据结构-->二叉树方法实现

从零开始学习数据结构-->线索二叉树

从零开始学习数据结构-->树、森林与二叉树的转换

从零开始学习数据结构-->大堆+小堆

从零开始学习数据结构-->AVL树之旋转算法

从零开始学习数据结构-->AVL树之插入算法

从零开始学习数据结构-->AVL树之删除算法 从零开始学习数据结构-->红黑树 从零开始学习数据结构-->图之邻接矩阵

从零开始学习数据结构-->图之邻接表

认真的人 自带光芒

9ecb9b7fc23913b58dc176c2d06bf93f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值