图的遍历(下)——邻接表

原创 2017年09月10日 14:11:03

概述

在我的上一篇博客:图的遍历(上)——邻接矩阵 中主要介绍了邻接矩阵的BFS和递归的DFS与非递归的DFS这3种遍历算法。在这篇博客我将主要叙述邻接表的以上3中遍历算法。首先来看看邻接表的表示方法。

邻接表主要是针对稀疏图中邻接矩阵造成的空间浪费而提出的。下面我们来看看邻接表的表示。
1)无向图的表示
这里写图片描述
2)有向图
这里写图片描述

(说明:对于BFS,DFS的递归与非递归算法在这篇文章就不再重复,如有不了解请移步我的上一篇博客:图的遍历(上)——邻接矩阵


广度优先遍历(BFS)

//广度优先遍历(BFS)
void BFS(int vertex){
    EdgeList* cur = this->Find(vertex);     //找到当前结点    
    queue<int> queue;                   //初始化队列 
    queue.push(cur->getVertex(cur));            //当前结点入队
    while(!queue.empty()){
        int index = queue.front();      //队头元素出队
        queue.pop();
        isvisited[index] = 1;           //标记为已访问 
        cout<<index<<" ";
        cur = this->Find(index);
        while(cur){     //与当前结点相邻且未被访问的结点入队 
            index = cur->getVertex(cur);
            if(isvisited[index] == 0){
                queue.push(index);
            }
            cur = cur->getNext();   
        } 
    }
}

递归深度优先遍历(DFS)

//递归深度优先遍历(DFS)
void DFS1(int vertex){
    vector<int> node;
    //找到当前结点 
    EdgeList* cur = this->Find(vertex);
    while(cur){     //寻找当前结点的邻接点 
        node.push_back(cur->getVertex(cur));
        cur = cur->getNext();
    }
    //打印当前结点 
    cur = this->Find(node[0]);
    int index = cur->getVertex(cur);
    this->isvisited[index] = 1;
    cout<<index<<" ";
    //一次堆当前结点的邻接点进行DFS 
    for(int i = 1 ; i < node.size() ; i++){
        cur = this->Find(node[i]);
        index = cur->getVertex(cur);
        if(this->isvisited[index] == 0){
            this->isvisited[index] = 1;
            this->DFS1(index);
        }
    }
}

非递归深度优先遍历(DFS)

//非递归深度优先遍历(DFS)
void DFS2(int vertex){
    stack<int> stack;
    EdgeList* cur = this->Find(vertex);     //查找当前元素 
    int index = cur->getVertex(cur);        //当前元素的顶点 
    stack.push(index);                      //顶点入栈 
    this->isvisited[index] = 1;             //标记为已访问 
    while(!stack.empty()){          //栈不空一直循环 
        index = stack.top();        //栈顶的顶点出栈 
        stack.pop();
        cout<<index<<" ";           //打印当前顶点 
        cur = this->Find(index); 
        while(cur){         //把当前顶点的邻接点依次入栈 
            index = cur->getVertex(cur);
            if(this->isvisited[index] == 0){
                stack.push(index);
                this->isvisited[index] = 1;
            }
            cur = cur->getNext();
        }
    }
} 

例子

下面的程序所基于的图结构够如下:
这里写图片描述

#include <iostream>
#include <vector> 
#include <queue> 
#include <stack>
#include <cstring> 
using namespace std;

//边表类 
class EdgeList{
    private:
        int vertex;
        EdgeList* next;
    public:
        EdgeList* Create(int vertex){
            EdgeList* list = new EdgeList;
            list->vertex = vertex;
            list->next = NULL;
            return list;
        }

        //寻找最后一个结点
        EdgeList* getLast(EdgeList* list){
            EdgeList* cur = list;
            while(cur){
                if(cur->next == NULL){
                    return cur;
                }
                cur = cur->next;
            }
        }

        //插入函数 
        EdgeList* Attach(EdgeList* list,int vertex){
            EdgeList* last = this->getLast(list);
            EdgeList* insert = insert->Create(vertex);
            last->next = insert;
            return list;
        }

        int getVertex(EdgeList* list){
            return list->vertex;
        }

        void Print(EdgeList* list){
            EdgeList* cur = list;
            while(cur){
                cout<<cur->vertex<<" ";
                cur = cur->next;
            }
        }

        EdgeList* getNext(){
            return this->next;
        }
}; 


class Graph{
    private:
        vector<EdgeList*> Edgelist;     //邻接表 
        int* isvisited;                 //访问数组 
        int Nv;         //顶点数
        int Ne;         //边数 
    public: 
        //构造函数 
        Graph(int nv ,int ne){
            this->Ne = ne;
            this->Nv = nv;
            this->Edgelist.reserve(nv);
            this->isvisited = new int[nv+1];
            memset(this->isvisited,0,sizeof(this->isvisited[0])*(this->Nv+1));
            cout<<"请输入顶点:"<<endl;
            //依次构造图的结点 
            for(int i = 0 ; i < this->Nv ; i++){
                int vertex;
                cin>>vertex;
                this->Edgelist[i] = new EdgeList;
                this->Edgelist[i] = this->Edgelist[i]->Create(vertex);
            }
            cout<<"请输入边:"<<endl;
            //依次构造无向图的边 
            for(int i = 0 ; i < this->Ne ; i++){
                int start,end;
                cin>>start>>end;
                //找到一条边的两个顶点 
                EdgeList* s1 = this->Find(start);       
                EdgeList* s2 = this->Find(end);
                s1->Attach(s1,end);
                s2->Attach(s2,start);
            } 
        }

        //按指定结点查找
        EdgeList* Find(int vertex){
            for(int i = 0 ; i < this->Nv ; i++){
                if(this->Edgelist[i]->getVertex(this->Edgelist[i]) == vertex){
                    return this->Edgelist[i];
                }
            } 
        }

        //打印邻接表函数 
        void Print(){
            for(int i = 0 ; i < this->Nv ; i++){
                EdgeList* list = this->Edgelist[i];
                list->Print(list);
                cout<<endl;
            }
        }

        //广度优先遍历(BFS)
        void BFS(int vertex){
            EdgeList* cur = this->Find(vertex);     //找到当前结点    
            queue<int> queue;                   //初始化队列 
            queue.push(cur->getVertex(cur));            //当前结点入队
            while(!queue.empty()){
                int index = queue.front();      //队头元素出队
                queue.pop();
                isvisited[index] = 1;               //标记为已访问 
                cout<<index<<" ";
                cur = this->Find(index);
                while(cur){     //与当前结点相邻且未被访问的结点入队 
                    index = cur->getVertex(cur);
                    if(isvisited[index] == 0){
                        queue.push(index);
                    }
                    cur = cur->getNext();   
                } 
            }
        }

        //重置访问数组 
        void reset(){
            memset(this->isvisited,0,sizeof(this->isvisited[0])*(this->Nv+1));
        } 

        //递归深度优先遍历(DFS)
        void DFS1(int vertex){
            vector<int> node;
            //找到当前结点 
            EdgeList* cur = this->Find(vertex);
            while(cur){     //寻找当前结点的邻接点 
                node.push_back(cur->getVertex(cur));
                cur = cur->getNext();
            }
            //打印当前结点 
            cur = this->Find(node[0]);
            int index = cur->getVertex(cur);
            this->isvisited[index] = 1;
            cout<<index<<" ";
            //一次堆当前结点的邻接点进行DFS 
            for(int i = 1 ; i < node.size() ; i++){
                cur = this->Find(node[i]);
                index = cur->getVertex(cur);
                if(this->isvisited[index] == 0){
                    this->isvisited[index] = 1;
                    this->DFS1(index);
                }
            }
        }

        //非递归深度优先遍历(DFS)
        void DFS2(int vertex){
            stack<int> stack;
            EdgeList* cur = this->Find(vertex);     //查找当前元素 
            int index = cur->getVertex(cur);        //当前元素的顶点 
            stack.push(index);                      //顶点入栈 
            this->isvisited[index] = 1;             //标记为已访问 
            while(!stack.empty()){          //栈不空一直循环 
                index = stack.top();        //栈顶的顶点出栈 
                stack.pop();
                cout<<index<<" ";           //打印当前顶点 
                cur = this->Find(index); 
                while(cur){         //把当前顶点的邻接点依次入栈 
                    index = cur->getVertex(cur);
                    if(this->isvisited[index] == 0){
                        stack.push(index);
                        this->isvisited[index] = 1;
                    }
                    cur = cur->getNext();
                }
            }
        } 
};

int main()
{
    cout<<"请输入顶点数与边数:"<<endl;
    int nv,ne;
    cin>>nv>>ne;
    Graph graph(nv,ne);
    cout<<"邻接表为:"<<endl;
    graph.Print();


    cout<<"请输入结点:"<<endl;
    int vertex;
    cin>>vertex; 

    cout<<"广度优先遍历(BFS)序列为:"<<endl;
    graph.BFS(vertex);
    cout<<endl;

    cout<<"递归深度优先遍历(DFS)序列为:"<<endl;
    graph.reset(); 
    graph.DFS1(vertex);
    cout<<endl; 

    cout<<"非递归深度优先遍历(DFS)序列为:"<<endl;
    graph.reset(); 
    graph.DFS2(vertex);
    cout<<endl; 

    return 0;
}

截图:
这里写图片描述

版权声明:本文为博主原创文章,未经博主允许不得转载。若需转载,请注明http://blog.csdn.net/qq_30091945 举报

相关文章推荐

图的邻接表表示及遍历

图也可以用邻接表表示。邻接表中存放各个结点的

图的邻接表及遍历

#include #include using namespace std; const int num=100; bool flag[num]={false}; struct Ed...
  • cap77
  • cap77
  • 2011-03-03 20:42
  • 387

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

图的邻接表和DFS遍历

邻接矩阵和邻接表的对比之前一篇文章我们学习了 图的邻接矩阵和DFS遍历, 邻接矩阵对于图来说是一种很不错的存储结构,但是也有特殊的情况,例如边数很少的时候。此时的邻接矩阵,只有(v0,v1)和(v1,...

图的遍历(基于邻接表)

//大家好,前几天更新的用邻接表来存储图的文章里面,并没有提及图的遍历这回事啊,所以呢,在这里不回来!! //在下要介绍的是“深度优先遍历” (如果下面的代码有错,请见谅) /////...

基于邻接表的无向图的深度广度遍历实现

邻接表,无向图,深度、广度遍历,测试通过 基本构建图的邻接表结构以及深度广度遍历 public class ALGraph { AdjList[] vertices; int vexNum; ...

图的存储结构与遍历

一、定义

图的遍历与输出 (邻接矩阵和邻接表)

#include #include #include "graph.h" using namespace std; int main() { freopen("data.in" , "...

邻接表-图的遍历-广度和深度优先遍历

数据结构目前学习的基本大概已经完成了,图的讲解也基本结束,本次试验就是图的遍历。   将常用的头文件放在t11.h中   #include"stdio.h" #include"string....

图的遍历——广度优先遍历——邻接表

图的遍历——广度优先遍历——邻接表

图的遍历——深度优先遍历——邻接表

图的遍历——深度优先遍历——邻接表
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)