图的邻接表表示、广度优先、深度优先搜索

图,就是我们在数据结构中学到的图,它是一种存储信息的结构。图是一类在实际应用中非常常见的数据结构,当数据规模大到一定程度时,如何对其进行高效计算即成为迫切需要解决的问题。最常见的大规模图数据的例子就是互联网网页数据,网页之间通过链接指向形成规模超过500 亿节点的巨型网页图。再如,Facebook 社交网络也是规模巨大的图,仅好友关系已经形成超过10 亿节点、千亿边的巨型图,考虑到Facebook 正在将所有的实体数据节点都构建成网状结构,其最终形成的巨型网络数据规模可以想见其规模。要处理如此规模的图数据,传统的单机处理方式显然已经无能为力,必须采用由大规模机器集群构成的并行图数据库。在处理图数据时,其内部存储结构往往采用邻接矩阵或邻接表的方式,在大规模并行图数据库场景下,邻接表的方式更加常用,大部分图数据库和处理框架都采用了这一存储结构。

本程序是基于图的邻接表存储方式实现的。遗憾的是没有实现带权图,有实现带权图的朋友欢迎留言指教!或加Q:374741295

package linkListGraph;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * @ClassName: Graph
 * @Description: 图结构实现,封装了图的dfs、bfs遍历算法
 * @author zhoupengcheng
 * @version 2015年5月17日下午5:07:34
 */
public class Graph {
	private ArrayList<Vertex> vertexList;// 用一个ArrayList保存图中的所有结点
	private boolean isDirected = false;// 标记是否为有向图
	private int nVerts = 0;// 保存总的顶点数

	private StackX theStack;// 深度优先搜寻时使用
	private Queue theQueue; // 广度优先搜索时使用
	private ArrayList<Vertex> bfs;// 在bfs函数中使用,保存bfs得到的结果序列
	private ArrayList<Vertex> dfs;// 在dfs函数中使用,保存dfs得到的结果序列

	public Graph() {
		vertexList = new ArrayList<Vertex>();
		dfs = new ArrayList<Vertex>();
		bfs = new ArrayList<Vertex>();
	}

	public Graph(boolean is) {
		this();
		this.isDirected = is;
	}

	public boolean isDirected() {
		return this.isDirected;
	}

	public ArrayList<Vertex> getVertexList() {
		return vertexList;
	}

	public ArrayList<Vertex> getDFS() {
		return dfs;
	}

	public ArrayList<Vertex> getBFS() {
		return bfs;
	}

	public void addVertex(Vertex vertex) {
		vertex.setIndex(nVerts);
		vertexList.add(vertex);
		nVerts++;
	}

	public void addEdge(int start, int end) {
		vertexList.get(start).addAdj(vertexList.get(end));
		if (!isDirected) {
			vertexList.get(end).addAdj(vertexList.get(start));
		}
	}

	public int getVertsCount() {
		return nVerts;
	}

	//深度优先迭代器
	public Iterator dfsIterator(){
        dfs();
        return new DfsIterator();
    } 

	//广度优先迭代器
	public Iterator bfsIterator(){
        bfs();
        return new BfsIterator();
    }  

	// 打印邻接表
	public void displayGraph() {
		for (int i = 0; i < vertexList.size(); i++) {
			printVertx(vertexList.get(i));
		}
	}

	public void printVertx(Vertex vertex) {
		ArrayList<Vertex> next = vertex.getAdj();
		if (next == null) {
			System.out.println(vertex.toString() + " 无邻接点!");
		} else {
			System.out.print(vertex.toString() + "邻接表:");
			for (int i = 0; i < next.size(); i++) {
				System.out.print(next.get(i).label + " ");
			}
			System.out.println();
		}
	}

	// 深度优先遍历
	public void dfs() {
		theStack = new StackX(nVerts);
		vertexList.get(0).wasVisted = true;
		dfs.add(vertexList.get(0));
		theStack.push(vertexList.get(0));
		Vertex vertex;
		while (!theStack.isEmpty()) {
			vertex = getAdjVertex((Vertex) theStack.peek());
			if (vertex == null) {
				theStack.pop();
			} else {
				vertex.wasVisted = true;
				dfs.add(vertex);
				theStack.push(vertex);
			}
		}
		// ------遍历完成,清除所有访问标志位--------
		for (int i = 0; i < getVertsCount(); i++) {
			vertexList.get(i).wasVisted = false;
		}

	}

	// 广度优先遍历
	public void bfs() {
		theQueue = new Queue(nVerts);
		vertexList.get(0).wasVisted = true;
		bfs.add(vertexList.get(0));
		theQueue.insert(vertexList.get(0));
		Vertex vertex1;
		while (!theQueue.isEmpty()) {
			Vertex vertex2 = (Vertex) theQueue.remove();
			while ((vertex1 = getAdjVertex(vertex2)) != null) {
				vertex1.wasVisted = true;
				bfs.add(vertex1);
				theQueue.insert(vertex1);
			}
		}
		// ------遍历完成,清除所有访问标志位--------
		for (int i = 0; i < getVertsCount(); i++) {
			vertexList.get(i).wasVisted = false;
		}
	}

	// 返回vertex顶点的一个未曾访问过的邻接点
	public Vertex getAdjVertex(Vertex vertex) {
		ArrayList<Vertex> adjVertexs = vertex.getAdj();
		for (int i = 0; i < adjVertexs.size(); i++) {
			if (!adjVertexs.get(i).wasVisted) {
				return adjVertexs.get(i);
			}
		}
		return null;
	}

	//专门写个迭代器来遍历结果
	private abstract class GraphIterator implements Iterator {
		int count = 0;
		public GraphIterator() {
		}

		public boolean hasNext() {
			return count != getVertsCount() ;
		}

		public Object next() {
			// TODO Auto-generated method stub
			return null;
		}

		public void remove() {
			// TODO Auto-generated method stub
		}
	}

	// 深度优先迭代
	private class DfsIterator extends GraphIterator {
		public DfsIterator() {
			super();
		}

		public Vertex next() {
			return dfs.get(count++);
		}
	}

	// 广度优先迭代
	private class BfsIterator extends GraphIterator {
		public BfsIterator() {
			super();
		}

		public Object next() {
			return bfs.get(count++);
		}
	}
}
package linkListGraph;

import java.util.Iterator;

public class GraphApp {

	public static void main(String[] args) {
		Graph myGraph = new Graph();
		Vertex vertex;
		myGraph.addVertex(new Vertex('A'));//位置为0
		myGraph.addVertex(new Vertex('B'));//位置为1
		myGraph.addVertex(new Vertex('C'));//位置为2
		myGraph.addVertex(new Vertex('D'));//位置为3
		myGraph.addVertex(new Vertex('E'));//位置为4
		myGraph.addVertex(new Vertex('F'));//位置为5
		myGraph.addVertex(new Vertex('G'));//位置为6
		myGraph.addVertex(new Vertex('H'));//位置为7
		myGraph.addVertex(new Vertex('I'));//位置为8
		myGraph.addVertex(new Vertex('J'));//位置为9
		myGraph.addVertex(new Vertex('K'));//位置为10
		myGraph.addEdge(0, 1);
		myGraph.addEdge(0, 2);
		myGraph.addEdge(0, 3);
		myGraph.addEdge(1, 4);
		myGraph.addEdge(1, 5);
		myGraph.addEdge(3, 7);
		myGraph.addEdge(3, 10);
		myGraph.addEdge(4, 6);
		myGraph.addEdge(5, 6);
		myGraph.addEdge(5, 9);
		myGraph.addEdge(7, 8);
		myGraph.addEdge(8, 10);
		myGraph.displayGraph();

		System.out.println("深度优先迭代遍历:");
		for (Iterator iterator = myGraph.dfsIterator(); iterator.hasNext();) {
			vertex = (Vertex) iterator.next();
			System.out.println(vertex.toString());
		}

		System.out.println("广度优先迭代遍历:");
		for (Iterator iterator = myGraph.bfsIterator(); iterator.hasNext();) {
			vertex = (Vertex) iterator.next();
			System.out.println(vertex.toString());
		}
	}
}
package linkListGraph;
import java.util.ArrayList;
/**
 * @ClassName:   Vertex
 * @Description: 顶点类,表示图中存储的顶点
 * @author       zhoupengcheng
 * @version      2015年5月17日下午4:31:54
 */
public class Vertex {
	public char label;
	public boolean wasVisted;
	public int indexId;//顶点的标号
	//由于采用"邻接表"方式表示图,所以每个顶点对象持有一个邻接表adjList
	private ArrayList<Vertex> adjacentList = null;

	public Vertex(char lab) // constructor
	{
		this.label = lab;
		this.wasVisted = false;
	}

	// 为节点添加邻接点
	public void addAdj(Vertex ver) {
		if (adjacentList == null)
			adjacentList = new ArrayList<Vertex>();
		adjacentList.add(ver);
	}

	//返回一个顶点的邻接表,在遍历图时需根据邻接表找下一个节点
	public ArrayList<Vertex> getAdj() {
		return this.adjacentList;
	}

	public void setIndex(int index) {
		this.indexId = index;
	}

	public String toString() {
		return "顶点 :" + label+" ";
	}
}
package linkListGraph;
/*
 * 深度优先遍历需要借助栈保存当前访问过的顶点
 */
public class StackX {
	//private int size=20;
	private Vertex[] stackArray;//用数组实现栈的存储(理论上链栈效率更高)
	private int top;
	public StackX(int size){
		stackArray=new Vertex[size];
		top=-1;
	}

	public Vertex pop(){
		return stackArray[top--];
	}

	public Vertex peek(){
		return stackArray[top];
	}

	public boolean isEmpty(){
		return top==-1;
	}

	public void push(Vertex vertex) {
		// TODO Auto-generated method stub
		stackArray[++top]=vertex;
	}
}
package linkListGraph;
/*
 * 广度优先需要借助队列保存当前已经访问过的顶点
 */
public class Queue {
	private int maxSize=20;
	private int front;//队头指针
	private int rear;//队尾指针
	private Vertex[] queArray;//用数组实现队列的存储(理论上链队列效率更高)

	public Queue(int size) {
		this.maxSize=size;
		queArray = new Vertex[maxSize];
		front = 0;
		rear = -1;
	}

	public void insert(Vertex value) {
		if (rear == maxSize - 1)
			rear = -1;
		queArray[++rear] = value;
	}

	// 返回被删除的元素
	public Vertex remove() {
		if (front == maxSize)
			front = 0;
		Vertex temp = queArray[front++];
		return temp;
	}

	public boolean isEmpty() {
		return (rear+1==front||(front+maxSize-1==rear));
	}
}
时间: 2024-10-25 22:50:59

图的邻接表表示、广度优先、深度优先搜索的相关文章

浅谈数据结构之图的邻接表深度和广度优先遍历(九)

邻接矩阵是一种不错的图存储结构,但是我们发现,对于边数相对较少的图,这种结构是存在对存储空间的极大浪费的.我们知道,顺序存储结构存在预先分配内存可能造成空间浪费的问题,于是引出了链式存储的结构.同样的,我们也可以考虑对边或弧使用链式存储的方式来避免空间浪费的问题.因此,对于图的存储结构,我们同样引入了一种数组与链表相组合的存储方法,我们一般称之为邻接表. 邻接表的处理方法是这样的:(1).图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易的读取顶点的信息,更加方便:另

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

1 /** 2 无向图的邻接表存储 3 深度优先遍历递归 4 广度优先遍历递归+非递归 5 */ 6 #include <stdio.h> 7 #include <string.h> 8 #include <malloc.h> 9 #define N 5 10 #define MAX 50 11 typedef struct A{ 12 int adjvex; 13 struct A* nextArc; 14 }Arc; 15 typedef struct node{

基于C++ STL图的邻接表表示及深度、广度搜索实现

基于C++ STL图的邻接表表示及深度.广度搜索实现,对图论的学习有帮助,代码如下: #include <iostream> #include <vector> #include <set> using namespace std; #define MAX(a, b) ((a) > (b) ? (a) : (b) ) //定义图的定点 typedef struct Vertex { int id; vector<int> connectors; //存

数据结构实验之图论二:基于邻接表的广度优先搜索遍历

数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) 输入 输入第一行为整数n(0< n <100),表示数据的组数. 对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,

SDUT 2142 【TEST】数据结构实验之图论二:基于邻接表的广度优先搜索遍历

数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Description 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) Input 输入第一行为整数n(0< n <100),表示数据的组数.对于每组数据,第一行是三个整数k,m,t(0<

数据结构学习笔记05图 (邻接矩阵 邻接表--&gt;BFS DFS)

数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边<v, w> 表示从v指向w的边(单行线) 不考虑重边和自回路 无向图:边是无向边(v, w) 有向图:边是有向边<v, w> 连通:如果从V到W存在一条(无向)路径,则称V和W是连通的 连通图(Connected Graph):如果对于图的任一两个顶点v.w∈V,v和w都是连通的,则称

数据结构之---C语言实现图的邻接表存储表示

// 图的数组(邻接矩阵)存储表示 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NAME 3 // 顶点字符串的最大长度+1 #define MAX_VERTEX_NUM 20 typedef int InfoType; // 存放网的权值 typedef char VertexType[MAX_NAME]; // 字符串类型 typedef enum{DG, DN, AG

图(邻接表)

我们先来看一个图 我们想将这个图的信息存储到邻接表中,我们需要一个数组保存节点信息,还要有一个节点用来保存与该节点相邻的节点信息. 1 typedef struct arc_node 2 { 3 int pos; 4 int distance; 5 struct arc_node * next; 6 } Arc_node;//保存Node节点的相邻节点信息 7 8 typedef struct node 9 { 10 node_type info; 11 Arc_node * next; 12

数据结构(10) -- 图的邻接表存储

////////////////////////////////////////////////////////// //图的邻接表存储 ////////////////////////////////////////////////////////// #include <iostream> #include <stdlib.h> using namespace std; //图的邻接表表示法 #define MaxVertexNum 100 enum GraphType{DG,