邻接表实现Dijkstra算法以及DFS与BFS算法

//============================================================================
// Name        : ListDijkstra.cpp
// Author      : fffff
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include<iostream>
#include<cstdlib>
#include<queue>

using namespace std;

#define MAXSIZE 100
#define INF (~(0x1<<31)) //最大值 0x7FFFFFFF

class ListUDG{
    /*
     * 内部类
     */
private:
    /*
     * 邻接表中的边节点
     * ivex:下一个节点的编号
     * nextEdge:指向下一个边节点的指针
     */
    class Enode{
    public:
        int ivex;
        int weight;
        Enode *nextEdge;
    };
    /*
     * 邻接表中的顶点节点
     * data:顶点节点的数据
     * firstEdge:顶点节点的第一条边
     */
    class Vnode{
    public:
        char data;
        Enode *firstEdge;
    };
private:
    int mVexNum;//顶点个数
    int mEdgNum;//边的条数
    Vnode mVexs[MAXSIZE];
    bool visited[MAXSIZE];
public:
    ListUDG();
    ListUDG(char vexs[],int vlen,char edge[][2],int elen,int weigh[]);
    ~ListUDG();
    char rChar();
    int getPost(char ch);
    int getmVexNum();
    int getmEdgNum();
    Vnode getVexs(int i){
        return mVexs[i];
    };
    int getWeight(int v,int u);
    void print();
    void BFS();
    void DFS();
    void DFSK(int k);
    void Dijkstra(ListUDG *listudg,int v,int pre[],int dist[]);
    void trace(ListUDG *listudg,int v,int u,int pre[]);
private:
    char readChar();
    int getPosition(char ch);
    void LinkLast(Enode *list,Enode *node);
};
ListUDG::ListUDG(char vexs[],int vlen,char edge[][2],int elen,int weigh[]){
    /*
     * 初始化顶点数与边的条数
     */
    mVexNum = vlen;
    mEdgNum = elen;
    /*
     * 初始化邻接表中的顶点节点
     */
    for(int i=0;i<mVexNum;i++){
        mVexs[i].data = vexs[i];
        mVexs[i].firstEdge = NULL;
    }
    /*
     * 初始化邻接表中的边节点
     */
    for(int i=0;i<mEdgNum;i++){
        char first = edge[i][0];
        char second = edge[i][1];
        int start = getPosition(first);
        int end = getPosition(second);

        Enode *enode1 = new Enode;
        enode1->ivex = end;
        enode1->weight = weigh[i];
        enode1->nextEdge = NULL;
        if(mVexs[start].firstEdge==NULL)
            mVexs[start].firstEdge = enode1;
        else
            LinkLast(mVexs[start].firstEdge,enode1);

        Enode *enode2 = new Enode;
        enode2->ivex = start;
        enode2->weight = weigh[i];
        enode2->nextEdge = NULL;
        if(mVexs[end].firstEdge==NULL)
            mVexs[end].firstEdge=enode2;
        else
            LinkLast(mVexs[end].firstEdge,enode2);
    }
};
ListUDG::ListUDG(){
    /*
     * 初始化顶点数与边的条数
     */
    cout<<"input num of Vexs and Edges : ";
    cin>>mVexNum>>mEdgNum;
    /*
     * 初始化邻接表中的顶点节点
     */
    for(int i=0;i<mVexNum;i++){
        cout<<"input data of "<<i<<" Vex:";
        mVexs[i].data = readChar();
        mVexs[i].firstEdge = NULL;
    }
    /*
     * 初始化邻接表中的边节点
     */
    for(int i=0;i<mEdgNum;i++){
            cout<<"input edge("<<i<<"):";
            char first = readChar();
            char second = readChar();
            int start = getPosition(first);
            int end = getPosition(second);

            cout<<"input weight of the edge:";
            int weight;
            cin>>weight;

            Enode *enode1 = new Enode;
            enode1->ivex = end;
            enode1->weight = weight;

            /********************-----ERROR-----********************
             * 两个构造方法都忘掉此句,导致出错,
             * 出错地方在调用方法LinkLast的时候无法判断nextEdge是否为空
             * 因为nextEdge没有被赋值
             *******************************************************/
            enode1->nextEdge = NULL;
            if(mVexs[start].firstEdge==NULL)
                mVexs[start].firstEdge = enode1;
            else
                LinkLast(mVexs[start].firstEdge,enode1);

            Enode *enode2 = new Enode;
            enode2->ivex = start;
            enode2->weight = weight;
            enode2->nextEdge = NULL;
            if(mVexs[end].firstEdge==NULL)
                mVexs[end].firstEdge = enode2;
            else
                LinkLast(mVexs[end].firstEdge,enode2);
    }
};
ListUDG::~ListUDG(){

};
char ListUDG::rChar(){
    return readChar();
};
int ListUDG::getPost(char ch){
    return getPosition(ch);
};
int ListUDG::getmVexNum(){
    return mVexNum;
};
int ListUDG::getmEdgNum(){
    return mEdgNum;
};
int ListUDG::getWeight(int v,int u){
    Enode *enode;
    if(v==u)
        return 0;
    else{
        enode = mVexs[v].firstEdge;
        while(enode){
            if(enode->ivex==u)
                return enode->weight;
            else
                enode = enode->nextEdge;
        }
        return INF;
    }
};
void ListUDG::print(){
    cout<<"ListUDG"<<endl;
    for(int i=0;i<mVexNum;i++){
        cout<<i<<" ("<<mVexs[i].data<<"): ";
        Enode *p = mVexs[i].firstEdge;
        while(p){
            cout<<p->ivex<<"("<<mVexs[p->ivex].data<<")["<<p->weight<<"] ";
            p = p->nextEdge;
        }
        cout<<endl;
    }
    return ;
};
char ListUDG::readChar(){
    char cha;
    cin>>cha;
    while(!((cha>=‘a‘&&cha<=‘z‘)||(cha>=‘A‘&&cha<=‘Z‘))){
        cin>>cha;
    }
    return cha;
};
int ListUDG::getPosition(char ch){
    for(int i = 0;i<mVexNum;i++){
        if(mVexs[i].data==ch)
            return i;
    }
    return -1;
}
void ListUDG::LinkLast(Enode*list,Enode *node){
    Enode *p = list;
    while(p->nextEdge)
        p = p->nextEdge;
    p->nextEdge = node;
    return;
};
/*
 * Dijkstra 算法----最短路径
 */
void ListUDG::Dijkstra(ListUDG *listudg,int v,int pre[],int dist[]){
    bool s[MAXSIZE];

    /*
     * 第一步:初始化S集合以及距离dist
     */
    for(int i=0;i<listudg->getmVexNum();i++){
        s[i] = false;
        dist[i] = listudg->getWeight(v,i);
        if(dist[i]==INF)
            pre[i] = -1;
        else
            pre[i] = v;
    }
    s[v] = true;
    dist[v] = 0;
    /*
     * 第二步:寻找dist中的最小值加入到S集合中
     */
    for(int i=1;i<listudg->getmVexNum();i++){
        int min = INF;
        int u = v;
        for(int j=0;j<listudg->getmVexNum();j++){
            if(s[j]==false&&dist[j]<min){
                min = dist[j];
                u = j;
            }
        }
        s[u] = true;//将顶点u加入到集合S中
        /*
         * 第三步:更新dist
         */
        for(int j=0;j<listudg->mVexNum;j++){
            if(s[j]==false&&listudg->getWeight(u,j)<INF){
                int newdist = dist[u] + listudg->getWeight(u,j);
                if(newdist<dist[j]){
                    dist[j] = newdist;
                    pre[j] = u;
                }
            }
        }
    }
};
void ListUDG::trace(ListUDG *listudg,int v,int u,int pre[]){
    int start = v;
    int end = u;
    while(start!=end){
        cout<<listudg->mVexs[end].data<<"<---";
        end = pre[end];
    }
    cout<<listudg->mVexs[start].data<<endl;
};
/*
 * 广度优先搜索邻接表
 */
void ListUDG::BFS(){
    for(int i=0;i<MAXSIZE;i++)
        visited[i] = false;
    queue<int>que;
    que.push(0);
    visited[0] = true;
    int out;
    Enode *outNext;
    while(!que.empty()){
        out = que.front();
        outNext = mVexs[out].firstEdge;
        que.pop();
        cout<<mVexs[out].data<<" ";

        /****************-----ERROR-----*****************
         * 此处刚开始将判断条件visited[outNext->ivex]==false
         * 写入while循环的判断语句中,导致某一个顶点的边链表没有
         * 访问完就结束了循环(可能某边之前已经访问过),丢掉了后面
         * 的节点
         ************************************************/
        while(outNext!=NULL){
            if(visited[outNext->ivex]==false){
                que.push(outNext->ivex);
                visited[outNext->ivex] = true;
                outNext = outNext->nextEdge;
            }else
                outNext = outNext->nextEdge;
        }
    }
    cout<<endl;
};
void ListUDG::DFS(){
    for(int i=0;i<MAXSIZE;i++)
        visited[i] = false;
    for(int i=0;i<mVexNum;i++)
        if(visited[i]==false)
            DFSK(i);
    cout<<endl;
};
void ListUDG::DFSK(int k){
    visited[k]=true;
    cout<<mVexs[k].data<<" ";
    Enode *enode = mVexs[k].firstEdge;
    while(enode){
        if(visited[enode->ivex]==false){
            DFSK(enode->ivex);
            enode = enode->nextEdge;
        }
        else

            /************-----ERROR-----*************
             *开始时候忘掉了写此句,导致顶点的边链表没有访问完
             *而到时enode没有向后移动,从而导致循环无法结束,因此
             *程序死循环
             ****************************************/
            enode = enode->nextEdge;

    }
    return ;
}
int main(){
    char vexs[]={‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘,‘g‘};
    char edges[][2]={
        {‘a‘,‘b‘},
        {‘a‘,‘d‘},
        {‘a‘,‘g‘},
        {‘b‘,‘f‘},
        {‘c‘,‘d‘},
        {‘c‘,‘g‘},
        {‘d‘,‘f‘},
        {‘e‘,‘g‘},
        {‘f‘,‘g‘}
    };
    int pre[MAXSIZE];
    int dist[MAXSIZE];
    int weight[]={1,3,2,2,6,4,3,7,1};
    int vlen = sizeof(vexs)/sizeof(vexs[0]);
    int elen = sizeof(edges)/sizeof(edges[0]);
    ListUDG *listudg1 = new ListUDG(vexs,vlen,edges,elen,weight);
    listudg1->print();
    listudg1->BFS();
    listudg1->DFS();
    listudg1->Dijkstra(listudg1,0,pre,dist);
    listudg1->trace(listudg1,0,2,pre);
    return 0;
}

运行结果如下

ListUDG
0 (a): 1(b)[1] 3(d)[3] 6(g)[2]
1 (b): 0(a)[1] 5(f)[2]
2 (c): 3(d)[6] 6(g)[4]
3 (d): 0(a)[3] 2(c)[6] 5(f)[3]
4 (e): 6(g)[7]
5 (f): 1(b)[2] 3(d)[3] 6(g)[1]
6 (g): 0(a)[2] 2(c)[4] 4(e)[7] 5(f)[1]
a b d g f c e
a b f d c g e
c<---g<---a
时间: 2024-08-11 05:43:59

邻接表实现Dijkstra算法以及DFS与BFS算法的相关文章

基本DFS与BFS算法(C++实现)

样图: DFS:深度优先搜索,是一个不断探查和回溯的过程,每探查一步就将该步访问位置为true,接着在该点所有邻接节点中,找出尚未访问过的一个,将其作为下个探查的目标,接着对这个目标进行相同的操作,直到回到最初的节点,此时图中所有节点都访问过了. BFS:广度优先搜索,是一个逐层遍历的过程,每探查一步就将该步访问位置为true,接着在该点所有邻接节点中,找出尚未访问过的一个,将其作为下个探查的目标,接着还是对该节点(而不是所选择的目标)剩下的未访问的点选择一个,作为下一个探查的目标,直到没有邻接

图的遍历算法:DFS、BFS

在图的基本算法中,最初需要接触的就是图的遍历算法,根据访问节点的顺序,可分为深度优先搜索(DFS)和广度优先搜索(BFS). DFS(深度优先搜索)算法 Depth-First-Search 深度优先算法,是一种用于遍历或搜索树或图的算法.沿着树的深度遍历树的节点,尽可能深的搜索树的分支. 当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点. 这一过程一直进行到已发现从源节点可达的所有节点为止. 如果还存在未被发现的节点, 则选择其中一个作为源节点并重复以上过程,整个进程反复

DFS,BFS算法

粗略的讲一下这两种算法,为老年痴呆做好准备(ノへ ̄.) DFS: 如上图,你将搜索整张图,而DFS的搜索方法就是,先一味的往前走!走到某个尽头后发现无路可走,后退.咦?后退一步有一个分岔口,这里有多个支路,选择一条没走过的继续走,碰到死胡同,后退,又到了这个分岔口,再去选择没走过的路,直到无路可走,然后返回上一个分岔口.具体过程如下:                                                                       (图中黑色数字均为遍历

做了一道跑大数据的最短路挂了,基于vector的二维模拟邻接表实现Dijkstra算法(*【模板】)

代码: #include <stdio.h> #include <string.h> #include <string> #include <vector> #include <algorithm> #define INF 2100000000 using namespace std; int n; struct node { int dd; int w; }t; vector<node>q[500001]; unsigned int

图论算法之DFS与BFS

概述(总) DFS是算法中图论部分中最基本的算法之一.对于算法入门者而言,这是一个必须掌握的基本算法.它的算法思想可以运用在很多地方,利用它可以解决很多实际问题,但是深入掌握其原理是我们灵活运用它的关键所在. 含义特点 DFS即深度优先搜索,有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念. 由于用到递归,当节点特别多且深度很大

图的两种存储(邻接矩阵和邻接表)和两种遍历(DFS和BFS)

图的表示有很多,形式不固定,我暂时先记录我已经懂了的,能写的两种即大多数人应该都知道的邻接矩阵和邻接表. 邻接矩阵: 这里的邻接矩阵和离散数学说的有一点不同,至少有向图的邻接矩阵不同(离散书上的有向图的邻接矩阵求法到是有点像求任意两点的最短路径的Floyd算法) 以上都是(我现有知识认为的)废话: 重点 : G : 表示图: Nv:表示图的点数: Ne:表示图的边数: 邻接矩阵 即是一个 Nv * Nv 的矩阵,矩阵是用来储存  权值的(如果是带权图且有边的话),如果是无权图的的话,如果两顶点有

【数据结构】邻接表的广度与深度遍历

邻接表:数组和链表相结合的方法.图中顶点一般用一个一维数组存储,也可以用单链表存储,每个顶点的邻接点构成一个线性表,一般为单链表. 无向图: 有向图: 代码: #include "stdio.h" #include "stdlib.h" #include "io.h" #include "math.h" #include "time.h" #define OK 1 #define ERROR 0 #defi

(编程训练)再回首,数据结构——无向图的邻接矩阵表示、DFS、BFS

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. [问题描述] 建立图的邻接矩阵存储结构,实现图的遍历 [基本要求] ·功能:建立图的邻接矩阵存储结构,实现图的BFS.DFS ·输入:输入连通图的顶点数.顶点信息.边数.顶点对序列及遍历的起始顶点序号 ·输出:图的广度优先搜索序列.深度优先搜索 [模块划分] 1. 建立有向图的邻接表 CreateAdjMatrix() 2. 以邻接

PTA 邻接表存储图的广度优先遍历(20 分)

6-2 邻接表存储图的广度优先遍历(20 分) 试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ); 其中LGraph是邻接表存储的图,定义如下: /* 邻接点的定义 */ typedef struct AdjVNode *PtrToAdjVNode; struct AdjVNode{ Vertex AdjV; /* 邻接点下标 */ PtrToAdjVNode Next; /*