1.邻接表实现(GraphAdjList)
import java.lang.reflect.Array;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* 稀疏图
* 邻接表实现
* @author Administrator
*/
public class GraphAdjList<E> implements IGraph {
/**
* 邻接表中表对应的链表的结点
*/
private static class ENode{
/**
* 邻接顶点序号
*/
int adjvex;
/**
* 存储边或弧相关的信息,如权值
*/
int weight;
/**
* 下一个邻接表结点
*/
ENode nextadj;
/**
*
* @param adjvex
* @param weight
*/
public ENode(int adjvex, int weight) {
this.adjvex = adjvex;
this.weight = weight;
}
}
/**
* 邻接表中表的顶点
* @param <E>
*/
private static class VNode<E>{
/**
* 顶点信息
*/
E data;
/**
* 邻接表的第一个结点
*/
ENode firstadj;
public VNode(E data) {
this.data = data;
}
}
/**
* 顶点数组,每个元素都是一个VNode结构 顶点信息+结点(顶点序号+下一个邻接表的结点)
*/
private VNode<E>[] vexs;
/**
* 顶点的实际数量
*/
private int numOfVexs;
/**
* 顶点的最大数量
*/
private int maxNumOfVexs;
/**
* 判断顶点是否被访问过
*/
private boolean[] visited;
@SuppressWarnings("unchecked")
public GraphAdjList(int maxNumOfVexs) {
this.maxNumOfVexs = maxNumOfVexs;
vexs = (VNode<E>[]) Array.newInstance(VNode.class, maxNumOfVexs);
}
/**
* 获取顶点的个数
*
* @return
*/
@Override
public int getNumOfVertex() {
return numOfVexs;
}
/**
* 插入顶点
*
* @param v
* @return
*/
@Override
public boolean insertVex(Object v) {
//数组已满
if (numOfVexs>=maxNumOfVexs){
return false;
}
VNode<E> vex = new VNode<>((E) v);
vexs[numOfVexs++] = vex;
return true;
}
/**
* 删除顶点
*
* @param v
* @return
*/
@Override
public boolean deleteVex(Object v) {
return false;
}
/**
* 定位顶点的位置
*
* @param v
* @return
*/
@Override
public int indexOfVex(Object v) {
for (int i = 0;i<numOfVexs;i++){
if (vexs[i].data.equals(v)){
return i;
}
}
return -1;
}
/**
* 定位指定位置的顶点
*
* @param v
* @return
*/
@Override
public Object valueOfVex(int v) {
if (v<0|| v>=numOfVexs){
return null;
}
return vexs[v].data;
}
/**
* 插入边 无向无权图
*
* @param v1
* @param v2
* @param weight
* @return
*/
@Override
public boolean insertEdge(int v1, int v2, int weight) {
if (v1 < 0 || v2 < 0 || v1 >= numOfVexs || v2 >= numOfVexs){
throw new ArrayIndexOutOfBoundsException();
}
insertDo(new ENode(v2, weight), vexs[v1]);
//双向
insertDo(new ENode(v1, weight), vexs[v2]);
return true;
}
/**
* vex-->node
* @param node 链式的新结点
* @param vex 顶点
*/
private void insertDo(ENode node, VNode<E> vex) {
// 索引为index2的顶点没有邻接顶点
if (vex.firstadj == null) {
vex.firstadj = node;
}
// 索引为index1的顶点有邻接顶点
else {
node.nextadj = vex.firstadj;
vex.firstadj = node;
}
}
/**
* 插入边 考虑什么类型
* 1:无向无权图
* 2:无向有权图
* 3:有向无权图
* 4:有向有权图
*
* @param edgeElement
* @return
*/
@Override
public boolean insertEdge(EdgeElement edgeElement) {
return false;
}
/**
* 删除边
*
* @param v1
* @param v2
* @return
*/
@Override
public boolean deleteEdge(int v1, int v2) {
if (v1 < 0 || v2 < 0 || v1 >= numOfVexs || v2 >= numOfVexs){
throw new ArrayIndexOutOfBoundsException();
}
// 删除索引为index1的顶点与索引为index2的顶点之间的边 v1-v2
ENode current = vexs[v1].firstadj;//v2当前结点的下一个结点
ENode previous = null;//v2当前结点,
while (current != null && current.adjvex !=v2){
//v2当前结点,
previous = current;
current = current.nextadj;
}
if (current !=null) {
//删除操作
previous.nextadj = current.nextadj;
current = null;//垃圾回收此结点
}
// 删除索引为index2的顶点与索引为index1的顶点之间的边 v2-v1
current = vexs[v2].firstadj;
while (current != null && current.adjvex != v1){
previous = current;
current = current.nextadj;
}
if (current!=null){
previous.nextadj = current.nextadj;
current = null;
}
return true;
}
/**
* 查找边
*
* @param v1
* @param v2
* @return
*/
@Override
public int getEdge(int v1, int v2) {
if (v1 < 0 || v2 < 0 || v1 >= numOfVexs || v2 >= numOfVexs) {
throw new ArrayIndexOutOfBoundsException();
}
//第一个结点
ENode current = vexs[v1].firstadj;
while (current != null){
if (current.adjvex == v2){
return current.weight;
}
current = current.nextadj;
}
return 0;
}
/**
* 深度优先搜索遍历(递归栈实现)
*
* @param v
* @return
*/
@Override
public String depthFirstSearchByDG(int v) {
return null;
}
/**
* 深度优先搜索遍历(非递归栈实现)
*
* @param v
* @return
*/
@Override
public String depthFirstSearch(int v) {
if (v < 0 || v >= numOfVexs) {
throw new ArrayIndexOutOfBoundsException();
}
visited = new boolean[numOfVexs];
StringBuilder sb = new StringBuilder();
Stack<Integer> stack = new Stack();
stack.push(v);
visited[v] = true;
ENode current;
while (!stack.isEmpty()){
v = stack.pop();
sb.append(vexs[v].data+",");
current = vexs[v].firstadj;
while (current != null ){
if (!visited[current.adjvex]){
stack.push(current.adjvex);
visited[current.adjvex] = true;
}
current = current.nextadj;
}
}
return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : null;
}
/**
* 广度优先搜索遍历
*
* @param v
* @return
*/
@Override
public String breadFirstSearch(int v) {
if (v < 0 || v >= numOfVexs) {
throw new ArrayIndexOutOfBoundsException();
}
visited = new boolean[numOfVexs];
StringBuilder sb = new StringBuilder();
Queue<Integer> queue = new LinkedList<>();
queue.offer(v);
visited[v]=true;
ENode current;
while (!queue.isEmpty()){
v = queue.poll();
sb.append(vexs[v].data+",");
current = vexs[v].firstadj;
while (current!=null){
if (!visited[current.adjvex]){
queue.offer(current.adjvex);
visited[current.adjvex] = true;
}
current = current.nextadj;
}
}
return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : null;
}
/**
* 查找源点到其它顶点的路径
*
* @param v
* @return
*/
@Override
public int[] dijkstra(int v) {
out();
if (v < 0 || v >= numOfVexs) {
throw new ArrayIndexOutOfBoundsException();
}
//初始化false
boolean[] st = new boolean[numOfVexs];
//存放源点到其他点的距离
int[] distance = new int[numOfVexs];
//初始化全为无穷大
for (int i = 0; i<numOfVexs;i++){
distance[i] = Integer.MAX_VALUE;
}
ENode current;
current = vexs[v].firstadj;
out(st,distance);
while (current!=null){
distance[current.adjvex] = current.weight;
current =current.nextadj;
}
distance[v] = 0;
st[v] = true;
//处理从源点到其余顶点的最短路径
for (int i = 0;i<numOfVexs;i++) {
int min = Integer.MAX_VALUE;
int index = -1;
//比较从源点到其余顶点的路径长度
for (int j = 0; j < numOfVexs; j++) {
//从源点到j顶点的最短距离还没有找到 //从源点到j顶点的最小路径
if (!st[j] && distance[j] < min) {
index = j;
min = distance[j];
}
}
out(st, distance);
//找到源点到索引为index顶点的最短路径
if (index != -1) {
st[index] = true;
}
//更新当前最短路径及距离
for (int w = 0; w < numOfVexs; w++) {
if (!st[w]) {
current = vexs[w].firstadj;
while (current != null) {
if (current.adjvex == index && (min + current.weight) < distance[w]) {
distance[w] = min + current.weight;
break;
}
current = current.nextadj;
}
}
}
}
return distance;
}
private void out(boolean[] st, int[] distance) {
System.out.printf("%s\t\t%s\t\t%s\t\t\n","顶点","距离","是否访问");
for (int i=0; i<numOfVexs;i++) {
System.out.printf("%s\t\t",vexs[i].data);
System.out.printf("%d\t\t",distance[i]);
System.out.printf("%b\t\t",st[i]);
System.out.println();
}
}
/**
* 打印二维数组边的权值
*/
@Override
public void out() {
ENode current;
for (int i = 0 ;i<numOfVexs;i++) {
System.out.print(vexs[i].data);
current = vexs[i].firstadj;
while (current != null){
System.out.print("--->("+vexs[current.adjvex].data+","+current.weight+")");
current = current.nextadj;
}
System.out.println();
}
}
}
2.测试
import org.junit.Before;
import org.junit.Test;
/**
* 连接矩阵
* @author Administrator
*/
public class GraphAdjListTest {
private GraphAdjList graphAdjList;
@Before
public void setUp() throws Exception {
graphAdjList = new GraphAdjList(10);
graphAdjList.insertVex("A");
graphAdjList.insertVex("B");
graphAdjList.insertVex("C");
graphAdjList.insertVex("D");
graphAdjList.insertVex("E");
graphAdjList.insertVex("F");
graphAdjList.insertVex("G");
graphAdjList.insertVex("H");
graphAdjList.insertVex("I");
graphAdjList.insertEdge(graphAdjList.indexOfVex("A"),graphAdjList.indexOfVex("B"),1);
// out();
graphAdjList.insertEdge(graphAdjList.indexOfVex("A"),graphAdjList.indexOfVex("D"),3);
graphAdjList.insertEdge(graphAdjList.indexOfVex("A"),graphAdjList.indexOfVex("E"),2);
graphAdjList.insertEdge(graphAdjList.indexOfVex("B"),graphAdjList.indexOfVex("D"),5);
graphAdjList.insertEdge(graphAdjList.indexOfVex("B"),graphAdjList.indexOfVex("C"),1);
graphAdjList.insertEdge(graphAdjList.indexOfVex("C"),graphAdjList.indexOfVex("F"),7);
graphAdjList.insertEdge(graphAdjList.indexOfVex("D"),graphAdjList.indexOfVex("G"),2);
graphAdjList.insertEdge(graphAdjList.indexOfVex("E"),graphAdjList.indexOfVex("G"),9);
graphAdjList.insertEdge(graphAdjList.indexOfVex("G"),graphAdjList.indexOfVex("H"),1);
graphAdjList.insertEdge(graphAdjList.indexOfVex("H"),graphAdjList.indexOfVex("I"),3);
}
@Test
public void getNumOfVertex() {
}
@Test
public void insertVex() {
}
@Test
public void deleteVex() {
}
@Test
public void indexOfVex() {
}
@Test
public void valueOfVex() {
}
@Test
public void insertEdge() {
}
@Test
public void insertEdge1() {
}
@Test
public void deleteEdge() {
}
@Test
public void getEdge() {
}
@Test
public void depthFirstSearchByDG() {
}
@Test
public void depthFirstSearch() {
String s = graphAdjList.depthFirstSearch(0);
System.out.println(s);
}
@Test
public void breadFirstSearch() {
String s = graphAdjList.breadFirstSearch(0);
System.out.println(s);
}
@Test
public void dijkstra() {
int[] dijkstra = graphAdjList.dijkstra(0);
for (int i : dijkstra) {
System.out.print(i+",");
}
}
@Test
public void out() {
graphAdjList.out();
}
}