图的遍历方式有两种,node
深度优先采用的是递归的方式来来实现,思想以下:ios
假设给定图G的初态是全部顶点均不曾访问过。在G中任选一顶点v为初始出发点(源点),
则深度优先遍历可定义以下:
首先访问出发点v,并将其标记为已访问过;而后依次从v出发搜索v的每一个邻接点w。若w不曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中全部和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。若此时图中仍有未访问的顶点,则另选一个还没有访问的顶点做为新的源点重复上述过程,直至图中全部顶点均已被访问为止。
流程图以下:
由于采用的是递归调用,那就须要有两个函数,主要的递归调用的函数是放在private中的;在public有一个函数来调用这个递归函数,
public函数流程图以下:
数组
private 函数以下:函数
在这里用的临界表的形式来存储无向图;
图的结构体的定义和我图的十字链表表示法中图的结构体定义差很少,只是增长了一个标记位。用来标记这个结点是否是被访问过。图示以下:
仍是要定义两个结构体,图的邻接表是采用数组+链表的方式来实现的。那链表的结构体定义以下:
测试
数组的结构体定义以下:this
代码以下:spa
// 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; }