本学期有一门课程叫做算法分析与设计,用的教材是机械工业出版社的《算法导论》中文版第三版。课程只包括这本书的图算法部分,也就是第22章到第26章的部分,授课老师是郭炅老师,郭老师的水平还是很高的,在这里对郭老师一学期的授课表示感谢。而这几篇关于图算法的博客,就是基于这门课程的实验来进行整理的。
我们知道图一般有两种表示方法:邻接链表和邻接矩阵。比如在下图中b与c分别是图a的邻接链表表示和邻接矩阵表示。
这第一个实验是很简单的,就是要求生成两个随机的图,一个有向图一个无向图。有向图两千条边左右,无向图一千条边左右,边的数量是大概的。100个顶点。要求能算出每个顶点的度。要求每次图是随机生成的,并且有良好的结构。这里要求的是用邻接链表结构来表示。计算出度和 入度当然也是用遍历邻接链表了。
具体实现代码如下
import java.util.*;
/**
*
* @author sdu20
*
* @param <T>
*/
public class GraphChain extends LinkedList{
public GraphChain(){
super();
}
public void insert(int i,int j){
add(i,j);
}
}
import java.util.*;
/**
* 邻接链表实现
* @author sdu20
*
* @param <T>
*/
public class LinkedDigraph<T> extends Graph {
private int n; //顶点数
private int e; //边数
GraphChain[] aList; //邻接表
private boolean directed;
private boolean weighted;
private int[] Reached;
public LinkedDigraph(int numberOfVertices,boolean dir){
if(numberOfVertices<0){
System.out.println("The number of vertices must be >= 0");
System.exit(0);
}else{
n = numberOfVertices;
e = 0;
aList = new GraphChain[n+1];
Reached = new int[n+1];
for(int i =1;i<=n;i++){
aList[i] = new GraphChain();
Reached[i] = 0;
}
directed = dir;
weighted = false;
}
}
public LinkedDigraph(int numberOfVertices,boolean dir,boolean wei){
if(numberOfVertices<0){
System.out.println("The number of vertices must be >= 0");
System.exit(0);
}else{
n = numberOfVertices;
e = 0;
aList = new GraphChain[n+1];
Reached = new int[n+1];
for(int i =1;i<=n;i++){
aList[i] = new GraphChain();
Reached[i] = 0;
}
directed = dir;
weighted = wei;
}
}
@Override
public int numberOfVertices() {
// TODO Auto-generated method stub
return n;
}
@Override
public int numberOfEdges() {
// TODO Auto-generated method stub
return e;
}
@Override
public boolean exitsEdge(int i, int j) {
// TODO Auto-generated method stub
if(i<1 || j<1 || i>n || j>n || aList[i].indexOf(j)==-1)
return false;
else
return true;
}
@Override
public void eraseEdge(int n1, int n2) {
// TODO Auto-generated method stub
if(n1>= 1 && n2>=1 && n1<=n && n2<=n){
if(aList[n1].contains(n2)){
int index = aList[n1].indexOf(n2);
aList[n1].remove(index);
e--;
}
}
}
/**
* 检查顶点是否有效
* @param theVertex
* @return
*/
public final boolean checkVertex(int theVertex){
if(theVertex<1 || theVertex >n)
return false;
else
return true;
}
@Override
public int degree(int n) {
// TODO Auto-generated method stub
if(directed()){
return 0;
}else{
if(checkVertex(n))
return aList[n].size();
return 0;
}
}
@Override
public int inDrgree(int vv) {
// TODO Auto-generated method stub
if(directed()){
if(checkVertex(vv)){
int sum = 0;
for(int j = 1;j<=n;j++)
if(aList[j].contains(vv))
sum++;
return sum;
}else
return 0;
}else{
return 0;
}
}
@Override
public int outDegree(int vn) {
// TODO Auto-generated method stub
if(directed()){
if(checkVertex(vn))
return aList[vn].size();
return 0;
}else
return 0;
}
@Override
public boolean directed() {
// TODO Auto-generated method stub
return directed;
}
@Override
public boolean weighted() {
// TODO Auto-generated method stub
return weighted;
}
@Override
/**
* 插入一条新的边
*/
public boolean insertEdge(edge e) {
// TODO Auto-generated method stub
int v1 = e.getVertex1();
int v2 = e.getVertex2();
if(v1<1 || v2<1 || v1>n || v2>n ){
//System.out.println("Illegal edge.");
return false;
}
//System.out.println(v1);
//System.out.println(v2);
//System.out.println(aList[v1].indexOf(v2));
if(!aList[v1].contains(v2)){
aList[v1].insert(0,v2);
this.e++;
return true;
}
return false;
}
public edge getEdge(int v1,int v2){
return null;
}
/**
* 输出图
*/
public void bianli(){
if(n==0){
System.out.println("Empty");
return;
}
if(directed){
if(weighted){
System.out.println("共有"+n+"个顶点,"+e+"条边");
for(int i = 1;i<=n;i++){
System.out.println(i+":"+"入度:"+inDrgree(i)+" 出度:"+outDegree(i)+aList[i].toString());
}
}else{
System.out.println("共有"+n+"个顶点,"+e+"条边");
for(int i = 1;i<=n;i++){
System.out.println(i+":"+"入度:"+inDrgree(i)+" 出度:"+outDegree(i)+aList[i].toString());
}
}
}
else{
System.out.println("共有"+n+"个顶点,"+e/2+"条边");
for(int i = 1;i<=n;i++){
System.out.println(i+":"+"度数:"+degree(i)+aList[i].toString());
}
}
}
}
/**
* 图的抽象类
* @author sdu20
*
* @param <T>对于有权图,T是边上权的数据类型,对于无权图,T是布尔类型
*/
public abstract class Graph<T> {
public Graph(){}
public abstract int numberOfVertices();
public abstract int numberOfEdges();
public abstract boolean exitsEdge(int n1,int n2);
public abstract boolean insertEdge(edge<T> e);
public abstract void eraseEdge(int n1,int n2);
public abstract int degree(int n);
public abstract int inDrgree(int n);
public abstract int outDegree(int n);
public abstract boolean directed();
public abstract boolean weighted();
}
/**
*
* @author sdu20
*
* @param <T><T>对于有权图,T是边上权的数据类型,对于无权图,T是布尔类型
*/
public class edge<T> {
private int v1;
private int v2;
private T weight;
public edge(int v1,int v2){
this.v1 = v1;
this.v2 = v2;
}
public edge(int v1, int v2, T weight){
this.v1 = v1;
this.v2 = v2;
this.weight = weight;
}
public void setWeight(T weight){
this.weight = weight;
}
public T getWeight(){
return weight;
}
public int getVertex1(){
return v1;
}
public int getVertex2(){
return v2;
}
}
import java.util.*; /** * 生成一个随机的图 * @author sdu20 * */ public class RandomGraph { LinkedDigraph graph; public static void main(String[] args) { // TODO Auto-generated method stub RandomGraph gra = new RandomGraph(true);
gra.bianli();}/** * * @param dir true代表有向图 * false代表无向图 */public RandomGraph(boolean dir){// Scanner in = new Scanner(System.in);// System.out.println("请输入顶点个数:");// int vnum = in.nextInt();graph = new LinkedDigraph(100,dir);if(dir){/** * 有向图 */for(int i = 0;i<2000;i++){int preV = (int)(Math.random()*100+1); int folV = (int)(Math.random()*100+1); edge e = new edge(preV,folV); while(!graph.insertEdge(e)){ preV = (int)(Math.random()*100+1); folV = (int)(Math.random()*100+1); e = new edge(preV,folV); }}}else{/** * 无向图 *///System.out.println("无向图");for(int i = 0;i<1000;i++){int preV=(int)(Math.random()*100+1); int folV=(int)(Math.random()*100+1); edge e1 = new edge(preV,folV); edge e2 = new edge(folV,preV); while(!(graph.insertEdge(e1)&&graph.insertEdge(e2))){ preV=(int)(Math.random()*100+1); folV=(int)(Math.random()*100+1); e1 = new edge(preV,folV); e2 = new edge(folV,preV); }}}}public void bianli(){graph.bianli();}}//RandomGraph gra = new RandomGraph(false);
运行结果截图如下所示
RandomGraph gra = new RandomGraph(true);