数据结构——图的深度遍历

图的遍历方式有两种,

  1. 深度优先
  2. 广度优先

深度优先采用的是递归的方式来来实现,思想如下:

假设给定图G的初态是所有顶点均未曾访问过。在G中任选一顶点v为初始出发点(源点),
则深度优先遍历可定义如下:
首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。

流程图如下:
因为采用的是递归调用,那就需要有两个函数,主要的递归调用的函数是放在private中的;在public有一个函数来调用这个递归函数,
public函数流程图如下:

image.png

private 函数如下:


image.png

在这里用的临界表的形式来存储无向图;
图的结构体的定义和我图的十字链表表示法中图的结构体定义差不多,只是增加了一个标记位。用来标记这个结点是不是被访问过。图示如下:
还是要定义两个结构体,图的邻接表是采用数组+链表的方式来实现的。那链表的结构体定义如下:

image.png

数组的结构体定义如下:


image.png

在这里是用无向图图的实现的,其实有向图的实现和这个差不多少,还是也可以采用图的邻接表来实现,其实基本一样,大体是一样的,还是要设置标记位。我是采用下面的图的测试的。

image.png

代码如下:

//  GraphList.cpp
//  深度优先遍历
//
//  Created by 橘子和香蕉 on 2018/11/25.
//  Copyright © 2018 橘子和香蕉. All rights reserved.
//


/*
 遇到的问题:
 1:首先是添加边;用户输入的两个结点,先要判断哪个结点是新添加的,是俩都是,还是一个是,,然后设置位置。添加结点先是将数据放在数组,然后要将它添加到相应的链表中去,那就要申请新结点,我就是在初始化结点的时候没有将结点中指针设置为NULL,才导致了我之后的错误,想想就觉得自己蠢。
2:在删除结点的时候要判断这个结点还有没有邻结点,若是没有,就要删除这个结点,
 */

#include <iostream>
using namespace std;
#define dataType char
#define MAXSIZE 100
typedef struct  node{
    int position;
    node *next;
}node;
typedef struct Box{
    dataType data;
    node *out;
    bool isAccess;
}Box;
class Graph{
private:
    Box base[MAXSIZE];
    int vertexNum;
    int edgeNum;
    int  locate(dataType data);
    
    void deleteEdgePrivate(int  startPosition,int endPositon);
    void def(int position);
    bool isNotHaveNevNode(dataType data);
    void moveNode(dataType data);
    
public:
    ~Graph();
    void init(int vertexNum,int edgeNum);
    void create();
    void printNode(dataType data);
    void printGraph();
    void addEdge(dataType start,dataType end);
    void deleteEdge(dataType start,dataType end);
    void depthErgodic(dataType data);
    
};
Graph::~Graph(){
    for (int i = 0; i<vertexNum; i++) {
        node  *p= base[i].out;
        node *h = p;
        while ( p != NULL) {
            
            h = p->next;
            if(h == NULL) return;
            delete p;
            p = h->next;
        }
    }
    //    delete []base;
}
void Graph::init(int vertexNum, int edgeNum){
    this->vertexNum = vertexNum;
    this->edgeNum = edgeNum;
}
int  Graph::locate(dataType data){
    for (int i = 0; i<vertexNum; i++) {
        if(base[i].data == data){
            return I;
        }
    }
    return -1;
}
void Graph::create(){
    cout<<"create Graph begin\n";
    for (int i = 0; i<vertexNum; i++) {
        cout<<"input node data\n";
        cin>>base[i].data;
        base[i].out = NULL;
        base[i].isAccess = false;
    }
    node *startNode,*endNode;
    int startPosition;
    int endPosition;
    dataType start;
    dataType end;
    for (int i = 0; i<edgeNum; i++) {
        cout<<"input edge start and end\n";
        cin>>start>>end;
        startPosition = locate(start);
        endPosition = locate(end);
        //创建链表。先是创建start指向end;
        //在创建end指向start;
        endNode = new node;
        endNode->position = endPosition;
        endNode->next =  base[startPosition].out;
        base[startPosition].out = endNode;
        
        startNode = new node;
        startNode->position = startPosition;
        startNode->next = base[endPosition].out;
        base[endPosition].out = startNode;
    }
    
    
}
void Graph::printNode(dataType data){
    int position = locate(data);
    if(position == -1){
        cout<<"data is not exist\n";
        return;
    }
    else{
        node *h = base[position].out;
        cout<<"the data of"<<data<<":\t";
        while (h!=NULL) {
            cout<<base[h->position].data<<"\t";
            h=h->next;
        }
    }
    cout<<"\n";
}
void Graph::printGraph(){
    for (int i = 0; i<vertexNum; i++) {
        printNode(base[i].data);
    }
}
void Graph::addEdge(dataType start, dataType end){
    
    int startPosition = locate(start);
    int endPosition = locate(end);
    if(startPosition == -1){
        base[vertexNum].data = start;
        base[vertexNum].out = NULL;
        startPosition = vertexNum;
        init(vertexNum +1 , edgeNum+1);
    }
    if(endPosition == -1){
        base[vertexNum].data = end;
        base[vertexNum].out = NULL;
        endPosition = vertexNum;
        init(vertexNum +1 , edgeNum+1);
    }
    if(startPosition == -1 && endPosition == -1){
        
        base[vertexNum].data = start;
        startPosition = vertexNum;
        init(vertexNum +1 , edgeNum+1);
        
        base[vertexNum].data = end;
        endPosition = vertexNum;
        init(vertexNum +1 , edgeNum+1);
    }
    node* endNode = new node;
    endNode->position = endPosition;
    endNode->next = base[startPosition].out;
    base[startPosition].out = endNode;
    
    node* startNode = new node;
    startNode->position = startPosition;
    startNode->next = base[endPosition].out;
    base[endPosition].out = startNode;
    
    
}


void Graph::deleteEdge(dataType start, dataType end){
    
    /*
     a:删除的时候要判断俩结点的位置,然后一个一个的删除,先是删除start 到end这条表
        然后接着删除end到start这条边;
        其实删除的操作都是一样的,然后我就将删除的操作独立了出来,写了一个函数,放到private中去,
        删除start 到end和删除end到start只不过就是在函数调用的时候颠倒就好了,但是这只限于无向图。
     */
    int startPosition= locate(start);
    int endPositon = locate(end);
    if(startPosition ==-1 || endPositon == -1){
        cout<<"node is not exist\n";
        return;
    }
    deleteEdgePrivate( startPosition,endPositon);
    deleteEdgePrivate(endPositon, startPosition);
    if( isNotHaveNevNode(start) == true){
        moveNode(start);
    }
    if(isNotHaveNevNode(end) == true){
        moveNode(end);
    }
}


void Graph::deleteEdgePrivate(int  startPosition,int endPositon){
    int n = 0;
    node * p = base[startPosition].out;
    node *h = base[startPosition].out;
    
    
    while (p != NULL) {
        
        if(n ==0 && p->position == endPositon ) {
            base[startPosition].out = p->next;
            delete p;
            return;
        }
        n++;
        if(n != 0 && p->position == endPositon){
            h->next = p->next;
            cout<<"  "<<base[p->position].data<<endl;
            delete p;
            return ;
        }
        h = p;
        p = p->next;
    }
}

void Graph::depthErgodic(dataType data){
    int position = locate(data);
    position == -1?cout<<"the data is not exist\n":cout<<"";
    def(position);
    
}
void Graph::def(int position){
    node *p;
    cout<<base[position].data<<endl;
    base[position].isAccess = true;
    p = base[position].out;
    
    while (p != NULL) {
        if(base[p->position].isAccess == false){
            def(p->position);
        }
        p = p->next;
    }
}
/*p
 判断还有没有邻结点
 */
bool Graph::isNotHaveNevNode(dataType data){
    int position = locate(data);
    return  base[position].out == NULL?true:false;
}
/*
 移动数据
 */
void Graph::moveNode(dataType data){
    int position = locate(data);
    for (int i = position; i<vertexNum ; i++) {
        base[i].data = base[i+1].data;
        base[i].out = base[i+1].out;
        base[i].isAccess = base[i+1].isAccess;
    }
    this->vertexNum -= 1;
}
int main(){
    Graph a;
    a.init(4, 4);
    a.create();
//    a.printNode('b');
//    a.printGraph();
    a.addEdge('d', 'e');
    a.printNode('d');
    a.printNode('e');
    a.deleteEdge('d', 'e');
    a.printNode('e');
    return 1;
}


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容