编写程序对给定的有向图(不一定连通)进行深度优先遍历_从零开始学习数据结构>图的非连通遍历...

这篇博客主要介绍了如何从零开始学习数据结构,特别是针对有向图的深度优先遍历。无论图是否连通,都将探讨使用邻接矩阵和邻接表来实现遍历的方法。
摘要由CSDN通过智能技术生成
连通图和非连通图是“图”的 2 种不同存储形式,其遍历方式完全不一样,这次就来看看图的非连通遍历。 1、连通图和非连通图 连通图:任意的一个顶点到任意的另外一个顶点都有着相应的路径所能够到达。 非连通图:只要找出了有一个顶点不能够到达另外一个顶点。 2、遍历 对于连通图来说,通过DFS或BFS就可以完成遍历; 对于非连通图来说,就得从每个顶点出发进行搜索,每一次的从一个新的顶点出发访问,每个顶点都要开始搜索一遍。 3、非连通图的遍历算法 (1)、不可取的算法:没有必要将非连通图生成森林,在由森林生成我们的遍历树,然后再进行树形结构的访问。 (2)、比较好的算法:直接调动我们之前编写好的DFS()函数;只要没有访问的顶点,我们就由该顶点出发进行深度优先遍历,这样就最终把整个非连通图就遍历完成。 (3)强连通图:针对有向图,有A-->B的边,一定也有B-->A的边。 (4)、遍历算法
 1void components(){  //非连通图的遍历
2    int n = Graph::getCurVertex(); 3    bool *visit = new bool[n]; 4 5    for(int i = 0; i  6        visit[i] = false; 7    } 8    for(i = 0; i //对每个顶点都看一下,是否访问过。4 9        if(!visit[i]){10            DFS(getValue(i), visit);11        }12    }1314    delete []visit;15}
4、完整代码、测试代码、测试结果 (1)、完整代码
  1#ifndef _GRAPH_H_
2#define _GRAPH_H_
3
4#include
5#include
6using namespace std;
7
8#define VERTEX_DEFAULT_SIZE        20
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    }297    void components(){  //非连通图的遍历298        int n = Graph::getCurVertex();299        bool *visit = new bool[n];300301        for(int i = 0; i 302            visit[i] = false;303        }304        for(i = 0; i 305            if(!visit[i]){306                DFS(getValue(i), visit);307            }308        }309310        delete []visit;311312    }313protected:314    void DFS(const Type &v, bool *visit){315        cout<"-->";316        int index = getVertexIndex(v);317        visit[index] = true;318        int w = getFirstNeighbor(v);319        while(w != -1){320            if(!visit[w]){321                DFS(getValue(w), visit);322            }323            w = getNextNeighbor(v, getValue(w)); 324        }325    }326private:327    Type *vertexList;  //存放顶点的数组328    int **edge;  //存放边关系的矩阵329};330331#endif
(2)、测试代码
 1#include"Graph2.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    gm.insertVertex('J');
15    gm.insertVertex('K');
16    gm.insertVertex('L');
17    gm.insertVertex('M');
18
19    gm.insertEdge('A','B');
20    gm.insertEdge('A','C');
21    gm.insertEdge('A','F');
22    gm.insertEdge('A','L');
23    gm.insertEdge('B','M');
24    gm.insertEdge('L','J');
25    gm.insertEdge('L','M');
26    gm.insertEdge('J','M');
27    gm.insertEdge('D','E');
28    gm.insertEdge('G','H');
29    gm.insertEdge('G','I');
30    gm.insertEdge('G','K');
31    gm.insertEdge('H','K');
32
33    gm.showGraph();
34
35    cout<<"------------------------------------------------"<<endl;
36    gm.DFS('A');
37    cout<<"Nul."<<endl;
38    gm.BFS('A');
39     cout<<"Nul."<<endl;
40    gm.components();
41    cout<<"Nul."<<endl;
42    return 0;
43
44}
(3)、测试结果 测试图的模型: 4b05040cf8c4ac1cfed2f69d8b03101d.png da417af18d371e247146bffd7bbd0407.png 推荐阅读: 从零开始学习数据结构-->入门篇 从零开始学习数据结构-->链表 从零开始学习数据结构-->线性表 从零开始学习数据结构-->栈 从零开始学习数据结构-->队列 从零开始学习数据结构-->矩阵+串 从零开始学习数据结构-->哈希表 从零开始学习数据结构-->散列桶 从零开始学习数据结构-->二叉树

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

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

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

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

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

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

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

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

从零开始学习数据结构-->图的遍历 认真的人 自带光芒

4dcf98b8f27b6b49014bd3ff2b134cfe.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值