有向图的深度/广度优先遍历算法

本文介绍了一种使用邻接表存储图的方法,并详细阐述了如何通过该存储方式实现有向图的深度优先搜索(DFS)和广度优先搜索(BFS)。通过实例演示了如何创建图并进行两种不同的遍历。

// 邻接表存储与广度和深度优先算法
#include <iostream> 
using namespace std;

#define MAX_VERTEX_NUM 100

typedef enum {
 DG,DN,UDG,UDN
}GraphKind;

typedef struct EdgeNode {
 int adjvex; // 存储邻接点在顶点中的位置
 struct EdgeNode *nextedge;
 int weight;
}EdgeNode;

typedef struct VexNode {
 char vex;
 EdgeNode *firstedge;
}VexNode;

 

typedef struct {
 VexNode vexs[MAX_VERTEX_NUM];
 int vexnum, edgenum;
 GraphKind kind;
}LGraph;

// 构造有向图的邻接表,顶点数n,边数 e
void CreateDG(LGraph &G, int n, int e) {
 char ch;
 int i, j;
 G.vexnum = n;
 G.edgenum = e;
 // 顶点信息初始化
 for (i = 0; i < n; i++) {
  cin >> ch;
  G.vexs[i].vex = ch;
  G.vexs[i].firstedge = NULL;
 }
 // 边的信息初始化
 for (int k = 0; k < e; k++) {
  cin >> i >> j;
  EdgeNode *p = new EdgeNode;
  p->adjvex = j;
  p->nextedge = G.vexs[i].firstedge;
  G.vexs[i].firstedge = p; // 采用头插法来构建
 }
}

// 有向图的深度优先算法
int visited[MAX_VERTEX_NUM];

void DFS(LGraph &G, int i) {
 visited[i] = 1;
 cout << G.vexs[i].vex << " ";
 int j; // 当前访问的节点信息
 EdgeNode *p;
 p = G.vexs[i].firstedge;
 while (p) {
  j = p->adjvex;
  if (!visited[j]) {
   DFS(G, j);
  }
  p = p->nextedge;
 }
}

void DFS_Traverse(LGraph &G) {

 for (int i = 0; i < G.vexnum; i++) {
  visited[i] = 0;
 }

 for (int i = 0; i < G.vexnum; i++) {
  if (!visited[i]) {
   DFS(G, i);
  }
 }
}

//  有向图的广度优先遍历
const int Queue_Size = 100;

typedef struct circlQueue {
 int *elem;
 int front, rear;
 int queueSize;
}circlQueue;

// 循环队列初始化
void init_circleQueue(circlQueue &Q) {
 Q.elem = new int[Queue_Size];
 Q.front = Q.rear = 0;
 Q.queueSize = Queue_Size;
}

// 入队列
void enterQueue(circlQueue &Q, int x) {
 // 判满
 if ((Q.rear + 1)%Q.queueSize == Q.front) {
  cout << "Queue OverFlow!" << endl;
 }
 Q.elem[Q.rear] = x;
 Q.rear = (Q.rear + 1) % Q.queueSize;
}

// 出队列
void outQueue(circlQueue &Q, int &e) {
 // 判空
 if (Q.front == Q.rear) {
  cout << "Queue Empty!" << endl;
 }
 e = Q.elem[Q.front];
 Q.front = (Q.front + 1) % Q.queueSize;
}

// 广度优先
void BFS_Traverse(LGraph &G) {
 for (int i = 0; i < G.vexnum; i++)
  visited[i] = 0;

 circlQueue Q;
 init_circleQueue(Q);
 int v1,v2;
 for (int i = 0; i < G.vexnum; i++) {
  if (!visited[i]) {
   visited[i] = 1;
   cout << G.vexs[i].vex << " ";
   enterQueue(Q, i);
   // 队列不空
   while (Q.rear != Q.front) {
    outQueue(Q, v1);
    EdgeNode *p;
    p = G.vexs[v1].firstedge;
    while(p){
     v2 = p->adjvex;
     if (!visited[v2]) {
      cout << G.vexs[v2].vex << " ";
      visited[v2] = 1;
      enterQueue(Q, v2);
     }
     p = p->nextedge;
    }
   }
  }
 }
}

int main() {
 LGraph G;
 int n, e;
 cout << "请输入顶点数目:" << endl;
 cin >> n;
 cout << "请输入边的数目:" << endl;
 cin >> e;
 CreateDG(G, n, e);
 cout << "深度优先搜索结果:" << endl;
 DFS_Traverse(G);
 cout << endl;
 cout << "广度优先搜索结果:" << endl;
 BFS_Traverse(G);

 system("pause");
 return 0;

}

转载于:https://www.cnblogs.com/codingtao/p/6430429.html

/* * (有向)图的深度优先遍历算法模板 */ package dsa; public abstract class DFS extends GraphTraverse { //变量 protected static int clock = 0;//遍历过程中使用的计时钟 //构造方 public DFS(Graph g) { super(g); } //深度优先遍历算法 protected Object traverse(Vertex v, Object info) {//从顶点v出发,做深度优先查找 if (UNDISCOVERED != v.getStatus()) return null;//跳过已访问过的顶点(针对非连通图) v.setDStamp(clock++); v.setStatus(DISCOVERED); visit(v, info);//访问当前顶点 for (Iterator it = v.outEdges(); it.hasNext();) {//检查顶点v Edge e = (Edge)it.getNext();//通过边e = (v, u) Vertex u = (Vertex)e.getVPosInV(1).getElem();//相联的每一顶点u switch (u.getStatus()) {//根据u当前的不同状态,分别做相应处理 case UNDISCOVERED ://若u尚未被发现,则 e.setType(TREE);//e被归类为“树边” traverse(u, info);//从u出发,继续做深度优先查找 break; case DISCOVERED ://若u已经被发现,但对其访问尚未结束,则 e.setType(BACKWARD);//将e归类为“后向跨边” break; default ://VISITED,即对u的访问已经结束 if (u.getDStamp() < v.getDStamp())//若相对于v,u被发现得更早,则 e.setType(CROSS);//将e归类为“横跨边” else//否则 e.setType(FORWARD);//将e归类为“前向跨边” break; } }//至此,v的所有邻居都已访问结束,故 v.setFStamp(clock++); v.setStatus(VISITED);//将v标记为VISITED return null;//然后回溯 } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值