无向图相关算法基础(c++实现)

来源:互联网 发布:mac如何卸载office 编辑:程序博客网 时间:2024/05/17 09:09

前言

       在《无向图相关算法基础(java实现)》的博文中,用java实现了无向图的基础算法,本文通过c++实现。
       前文已经将无向图基础算法的概念描述的很清楚,本文不再累述,直接上代码。

代码

       本文涉及到的类如下:

  • Undigraph.h 无向图类,用于无向图的创建。
    Undigraph.cpp
  • BreadthFirstSearch.h 广度优先类,提供广度优先算法及两点间最短路径算法。
    BreadthFirstSearch.cpp
  • TestMain.cpp 主函数,用于测试。

       以上类,在VS2008开发环境测试通过,具体代码如下:
       Undigraph.h:

#ifndef Undigraph_H#define Undigraph_H/*-------------------------------------------------------------------------------------------------------------------------程序名称:Undigraph2016年12月 描述:创建无向图邻接链表数据结构//------------------------------------------------------------------------------------------------------------------------*//*------------------------------------------------------【头文件】---------------------------------------------------------描述:包含程序所依赖的头文件//------------------------------------------------------------------------------------------------------------------------*/#include <list> using namespace std;/*------------------------------------------------------【类声明】---------------------------------------------------------描述:无向图邻接链表类,用于创建无向图邻接链表数据结构//------------------------------------------------------------------------------------------------------------------------*/class Undigraph{    private:         int verticals;//顶点个数        int edges;//边的个数        list<int> *AdjacencyGraph;//指向邻接链表的指针    public:        /**/        Undigraph(int vertical);//构建函数,根据参数“vertical”构建邻接链表,类型为list<int>[vertical],vertical为顶点个数,此时list<int>都为空,调用AddEdge()函数添加边后,完成整个邻接链表的创建。        int GetVerticals();//返回顶点个数        int GetEdges();//返回边个数        void AddEdge(int verticalStart,int verticalEnd);//根据参数“verticalStart”、“verticalEnd”,在无向图中录入边数据,完成无向图的邻接链表数据结构。        list<int>* GetAdjacencyGraph(int vetical);//根据参数"vetical"返回该顶点的邻接表        void PrintGraph();//打印该无向图};#endif

Undigraph.cpp:

#include "Undigraph.h" /*------------------------------------------------------【Undigraph()构造函数】---------------------------------------------描述:根据参数“vertical”,创建邻接链表参数:1:int vertical(图的顶点个数)其它:执行该函数后,构建的数据结构如下:      0      1      2      3      4      5      6//-------------------------------------------------------------------------------------------------------------------------*/Undigraph::Undigraph(int vertical){    this->verticals = vertical;    this->edges = 0;    AdjacencyGraph = new list<int>[this->verticals];}/*------------------------------------------------------【GetVerticals() 函数】---------------------------------------------描述:返回图的顶点个数参数:返回值:图的顶点个数//-------------------------------------------------------------------------------------------------------------------------*/int Undigraph::GetVerticals(){    return verticals;}/*------------------------------------------------------【GetEdges() 函数】---------------------------------------------描述:返回图的边个数参数:返回值:图的边个数//-------------------------------------------------------------------------------------------------------------------------*/int Undigraph::GetEdges(){    return edges;}/*------------------------------------------------------【AddEdge()函数】---------------------------------------------描述:根据参数“verticalStart”、“verticalEnd”,创建邻接链表的边参数:1:int verticalStart(边的起始顶点)      2:int verticalEnd(边的结束顶点)其它:执行该函数8次,录入8条边后,构建的数据结构如下:      0->6->2->1->5      1->0      2->0      3->5->4      4->5->6->3      5->3->4->0      6->0->4至此,无向图邻接链表数据结构构建完毕//-------------------------------------------------------------------------------------------------------------------------*/void Undigraph::AddEdge(int verticalStart,int verticalEnd){    AdjacencyGraph[verticalStart].push_back(verticalEnd);    AdjacencyGraph[verticalEnd].push_back(verticalStart);    this->edges++;}/*------------------------------------------------------【GetAdjacencyGraph 函数】---------------------------------------------描述:根据参数"vetical",返回该顶点的邻接表参数:1:int vetical(顶点)返回值:与参数顶点对应的,邻接链表其它:例如输入参数“vetical”为0,则返回的list中的数据为list(6、2、1、5)//-------------------------------------------------------------------------------------------------------------------------*/list<int>* Undigraph::GetAdjacencyGraph(int vetical){    return &AdjacencyGraph[vetical];}/*------------------------------------------------------【PrintGraph 函数】---------------------------------------------描述:打印图结构,适用于控制台程序参数:返回值:其它:调用后,将在cmd窗口输出图的结构图,该函数用于测试,对逻辑无影响//-------------------------------------------------------------------------------------------------------------------------*/void Undigraph::PrintGraph(){    printf("无向图邻接链表数据结构如下:\n");    for(int i=0;i<this->verticals;i++)    {        printf("%d->",i);        for(list<int>::iterator j = this->AdjacencyGraph[i].begin();j!=AdjacencyGraph[i].end();j++)        {            printf("%d->",*j);        }        printf("\n");    }}

BreadthFirstSearch.h:

#ifndef BreadthFirstSearch_H#define BreadthFirstSearch_H//-------------------------------------------------------------------------------------------------------------------------//程序名称:BreadthFirstSearch//2016年12月 //描述:广度优先遍历,两点间最短路径//-------------------------------------------------------------------------------------------------------------------------//------------------------------------------------------【头文件】---------------------------------------------------------//描述:包含程序所依赖的头文件//-------------------------------------------------------------------------------------------------------------------------#include <stack> #include <queue>#include "Undigraph.h"using namespace std;//------------------------------------------------------【类声明】---------------------------------------------------------//描述:基于类“Undigraph”构建的无向图邻接链表,实现广度优先遍历、两点间最短路径//-------------------------------------------------------------------------------------------------------------------------class BreadthFirstSearch{private:    bool *marked;//布尔类型数组,用于记录顶点是否被访问,true代表已经被访问,false代表未被访问    int *edgeTo;//整形数组,用于记录起点到终点所有的路径,最终根据该数组生成两点间最短路径    int sourceVetical;//起始顶点    void bfs(Undigraph g,int s);//广度优先遍历public:    BreadthFirstSearch(Undigraph g,int s);//构造函数    bool HasPathTo(int v);//根据参数"v",判断起始顶点到该顶点是否有路径    stack<int>* PathTo(int v);//返回起始顶点“sourceVetical”到顶点“V”的最短路径    void printEdgeToAndMarked();//打印数组edgeTo和marked内容。};#endif

BreadthFirstSearch.cpp:

#include "BreadthFirstSearch.h"/*---------------------------------------------【BreadthFirstSearch()构造函数】---------------------------------------------描述:根据参数"Undigraph g"、"int s",创建广度优先遍历需要的布尔、整型数组。参数:1:Undigraph g(无向图对象)      2:int s(最短路径的起始点)其它:执行该函数后,构建的数据结构如下:      1、起始顶点为"0"      2、布尔、整型数组如下:         marked 0|false                 edgeTo 0|65535                      1|false                        1|65535                2|false                        2|65535                3|false                        3|65535                4|false                        4|65535                5|false                        5|65535                6|false                        6|65535     3、edgeTo整型数组用65535代表无穷大,代表无数据,因为有的时候顶点会为“0”,所以用无穷大代表无数据---------------------------------------------------------------------------------------------------------------------------*/BreadthFirstSearch::BreadthFirstSearch(Undigraph g,int s){    marked = new bool[g.GetVerticals()];//创建布尔型数组    edgeTo = new int[g.GetVerticals()];//创建整型数组    for(int i = 0;i<g.GetVerticals();i++)//数组付初始值    {        marked[i] = false;        edgeTo[i] = 0xFFFF;    }    this->sourceVetical = s;//获得起始顶点    bfs(g,s);//调用广度优先函数}/*---------------------------------------------【bfs()函数】---------------------------------------------描述:根据参数"Undigraph g"、"int s",对图进行广度优先遍历并填充edgeTo整型数组。参数:1:Undigraph g(无向图对象)      2:int s(最短路径的起始点)其它:执行该函数后,构建的数据结构如下:      1、起始顶点为"0"      2、布尔、整型数组如下:         marked 0|true                 edgeTo 0|65535                      1|ture                        1|0                2|ture                        2|0                3|ture                      ->3|5                4|ture                        4|6                5|ture                      ->5|0                6|ture                        6|0     3、程序执行后,数组edgeTo得到的是0到各个顶点的路径。如果所示,通过edgeTo[]数组即可得到0到3的路径为0->5->3---------------------------------------------------------------------------------------------------------------------------*/void BreadthFirstSearch::bfs(Undigraph g,int s){    queue<int>* q = new queue<int>();//创建队列    marked[s] = true;//将顶点在数组marked中设置为true,表示已访问过    q->push(s);//将顶点放入队列    while(q->size()!=0)    {        int v = q->front();//从队列中取出一个值        q->pop();//并将该值弹出队列        for each(int w in *g.GetAdjacencyGraph(v))//根据该值获得邻接链表。例如,如果V=0,则返回的邻接链表list为list(6,2,1,5),并对list中每个值做for each中的操作        {            if(!marked[w])//如果该值没有被访问过。            {                edgeTo[w] = v;//将该值对应的边添入edgeTo数组                marked[w] = true;//标记该值已经访问过                q->push(w);//将该值放入队列            }        }    }}/*------------------------------------------------【HasPathTo()函数】---------------------------------------------------描述:起始点到顶点“v”之间是否有路径参数:1:int v(任意顶点)返回值:true(有路径),false(无路径)---------------------------------------------------------------------------------------------------------------------------*/bool BreadthFirstSearch::HasPathTo(int v){    return marked[v];}/*------------------------------------------------【PathTo()函数】---------------------------------------------------描述:获得起始点到顶点“v”的路径参数:1:int v(任意顶点)返回值:stack<int>,存放两点间路径,例如:       stack<int>:                 0|0                 1|5                 2|3       存放的是路径0->5->3,既起始点0到终点3的路径---------------------------------------------------------------------------------------------------------------------------*/stack<int>* BreadthFirstSearch::PathTo(int v){    if(!HasPathTo(v))//判断两点之间是否有路径    {        return NULL;    }    stack<int>* path = new stack<int>();//创建栈,用于存储路径    for(int x = v; x!=sourceVetical; x=edgeTo[x])//该循环用于创建路径    {        path->push(x);    }    path->push(sourceVetical);    return path;}/*----------------------------------------【printEdgeToAndMarked()函数】------------------------------------------------描述:打印数组marked与edgeTo的内容其它:该函数是测试用的函数,与具体业务逻辑无关---------------------------------------------------------------------------------------------------------------------------*/void BreadthFirstSearch::printEdgeToAndMarked(){    printf("edgeTo[]数组内容:\n");    for(int i=0;i<7;i++)    {        printf("%d:%d\n",i,edgeTo[i]);    }    printf("marked[]数组内容:\n");    for(int i=0;i<7;i++)    {        if(marked[i])        {            printf("%d:%s\n",i,"true");        }else        {            printf("%d:%s\n",i,"false");        }    }}

TestMain.cpp:

#include <stdio.h>#include "Undigraph.h"//无向图#include"DepthFirstPaths.h"//深度优先遍历#include"BreadthFirstSearch.h"//广度优先遍历/*  无向图邻接表:                 无向图:                                          0->6->2->1->5                  0-------------6  1->0                           |\ \          |  2->0                           | 1 2         |  3->5->4                        |      3      |  4->5->6->3                     |     / \     |  5->3->4->0                     |    /   \    |           6->0->4                        |   /     \   |                                  |  /       \  |                                 | /         \ |                                 |/           \|                                 5-------------4 */void main(){      /*------------------------------------------------------无向图初始化----------------------------------------------------------------*/    Undigraph *g = new Undigraph(7);//7个顶点    g->AddEdge(0,6);//输入边数据,不要重复输入边的数据    g->AddEdge(0,2);    g->AddEdge(0,1);    g->AddEdge(0,5);    g->AddEdge(4,3);    g->AddEdge(4,5);    g->AddEdge(3,5);    g->AddEdge(6,4);    g->PrintGraph();//打印图    /*-----------------------------------------------------广度优先遍历-----------------------------------------------------------------*/    BreadthFirstSearch* bfs = new BreadthFirstSearch(*g,0);//初始化广度优先,g为邻接表,0为起始顶点。    stack<int> *s = bfs->PathTo(3);//获得03的最小路径,并存储在栈s中    printf("广度优先路径开始:");    while(!s->empty())//打印最小路径    {        printf("%d->",s->top());        s->pop();    }    printf("结束:\n");    bfs->printEdgeToAndMarked();//打印数组edgeTo与marked的内容    /*-----------------------------------------------------深度优先遍历-----------------------------------------------------------------    DepthFirstPaths *dfs = new DepthFirstPaths(*g,0);    stack<int> *ss = dfs->PathTo(3);    printf("深度优先路径开始:");    while(!ss->empty())//打印最小路径    {        printf("%d->",ss->top());        ss->pop();    }    printf("结束:\n");   */    /*------------------------------------------------------清除资源-------------------------------------------------------------------*/    delete g;    delete bfs;    delete s;    //delete dfs;    //delete ss;}

执行效果

这里写图片描述

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕初期肛裂出血怎么办 胃疼怎么办怎么缓解胃 脚踝崴了肿了怎么办 脚扭了脚背肿了怎么办 儿童脚扭伤肿了怎么办 脚关节扭伤肿了怎么办 小孩脚扭伤肿了怎么办 抱小孩腰扭伤了怎么办 跳舞把腰拉伤了怎么办 脚不小心扭伤了怎么办 娱乐之太帅了怎么办txt 走路走多了脚痛怎么办 胃疼怎么办简单按摩法 经常胃疼的厉害怎么办 半夜胃疼的厉害怎么办 吃消炎药伤胃了怎么办 吃药伤胃了胃疼怎么办 宝宝吃药伤胃了怎么办 胃胀胃痛怎么办快速解决方法 半夜2点3点胃疼怎么办 晚上吃多了胃疼怎么办 骨折打石膏后痒怎么办 脚脖子崴了肿了怎么办 喝酒喝的吐血了怎么办 感冒后咳嗽有痰怎么办 嗓子里老是有痰怎么办 物业把水停了怎么办 机洗衬衫缩水了怎么办 羊绒大衣洗缩水了怎么办 棉质衣服缩水了怎么办 衣服洗了变小了怎么办 毛衣洗后缩水了怎么办 鼻子又大又塌怎么办 苹果6被停用了怎么办 苹果6s手机停用怎么办 苹果4手机已停用怎么办 苹果手机5停用了怎么办 老公被骗300多万怎么办 苹果手机被抹除怎么办 钓鱼邮件点开了怎么办 幼犬吃多了拉稀怎么办