zoukankan      html  css  js  c++  java
  • 有向网的各种功能实现

    有向网的各种功能实现:

    1:在邻接矩阵、邻接表和逆邻接表之间转换。

    2:完成增加顶点和删除顶点的功能,删除顶点也要删除与之关联的边;

    3:完成增加边和删除边的功能;

    4:完成图的深度优先遍历和广度优先遍历;

    5:广度优先的生成树并对生成树进行遍历

    6:判断图的连通性,输出连通分量的个数;

    7:判断图中是否存在环;

    8:判断uv是否存在路径;

    9:实现DijkstraFloyd算法求最短路径;

    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    import java.util.Stack;
    
    
    public class DiNet<AnyType> {
    
    	class Ver<AnyType>{      //存储顶点
    		int data;
    		Arc firstArc;
    		boolean visit;
    		boolean known;
    		Ver path;
    		int dist;
    		int inDeg;
    		public Ver(int data){
    			this.data=data;
    			this.firstArc=null;
    			this.inDeg=0;
    		}
    		public Ver(int dist,int data){
    			this.dist=dist;
    			this.data=data;
    		}
    	}
    	class Arc<AnyType>{         //存储邻接点
    		int adjVex;
    		Arc nextArc;
    		int weight;
    		public Arc(int adjVex,int weight){
    			this.adjVex=adjVex;
    			this.nextArc=null;
    			this.weight=weight;
    		}
    		
    	}
    	class CSNode<AnyType>{     //孩子兄弟表示法  结点定义
    		int data;
    		CSNode firstChild;
    		CSNode nextSibling;
    		public CSNode(int data){
    			this.data=data;
    			this.firstChild=null;
    			this.nextSibling=null;
    		}
    		public CSNode(){
    			this.firstChild=null;
    			this.nextSibling=null;
    		}
    	}
    	Ver vertexts[];
    	Scanner sc=new Scanner(System.in);
    	int count=0;    //连通性标志
    	Ver begin,end;    //判断是否存在环时用到,路径的开始与结尾
    	boolean flag;//是否存在环的标识符
    //创建图
    	public Ver[] creatNet(){
    		System.out.println("请输入顶点个数");
    		int verNumber=sc.nextInt();
    		System.out.println("请输入要创建的网的边数:");
    		int edgeNumber=sc.nextInt();
    		System.out.println("请输入各个节点的数据:");
    		vertexts=new Ver[verNumber];
    		for(int i=0;i<verNumber;i++){                                        //将顶点存入数组中
    			vertexts[i]=new Ver(sc.nextInt());
    		}
    		System.out.println("请输入各条边(顶点在数组中的下标)及边的权重:");
    		for(int i=0;i<edgeNumber;i++){                    //输入边的弧头w,弧尾v,权重we,
    			int v=sc.nextInt();
    			int w=sc.nextInt();
    			int we=sc.nextInt();
    			Arc p=new Arc(w,we);
    			p.nextArc=vertexts[v].firstArc;               
    			vertexts[v].firstArc=p;
    			vertexts[w].inDeg++;                   //弧头指向的顶点入度加一
    		}
    		return vertexts;
    	} 
    //获取第一个邻接点
    	public int firstArc(int v){
    		Arc p=vertexts[v].firstArc;
    		if(p==null)
    			return -1;
    		return p.adjVex;
    	}
    //获取v相对于w的下一个邻接点
    	public int nextArc(int v,int w){
    		Arc p=vertexts[v].firstArc;
    		while(p.adjVex!=w){
    			p=p.nextArc;
    		}
    		if(p.nextArc==null)
    			return -1;
    		return p.nextArc.adjVex;
    	}
    //DFS
    	public void DFS(int v){
    		int w;
    		vertexts[v].visit=true;
    		System.out.print(vertexts[v].data+"  ");
    		for(w=firstArc(v);w>=0;w=nextArc(v,w)){
    			if(vertexts[w].visit==false){
    				DFS(w);		
    			}
    		}
    	}
    	public void DFSTravel(){
    		for(int i=0;i<vertexts.length;i++){    //令所有顶点的visit都为false
    			vertexts[i].visit=false;
    		}
    		System.out.println("深度优先遍历");
    		for(int v=0;v<vertexts.length;v++){    //对每个没有被访问过的顶点都要进行深度优先遍历
    			if(vertexts[v].visit==false){			
    			    count++;                         //若count最终大于1,说明网无法从一个顶点开始一次遍历完,即为非连通图
    				DFS(v);	
    			}
    		}
    		System.out.println();
    	}
    //BFS
    	public void BFS(){
    		int w;
    		Queue<Integer> q=new LinkedList<Integer>();
    		for(int i=0;i<vertexts.length;i++){    //令所有顶点的visit都为false
    			vertexts[i].visit=false;
    		}
    		System.out.println("广度优先遍历");
    		for(int i=0;i<vertexts.length;i++){
    			if(vertexts[i].visit==false){
    				vertexts[i].visit=true;          //标记为已访问
    				System.out.print(vertexts[i].data+" ");
    				q.add(i);                        //将访问过的顶点入队
    				while(!q.isEmpty()){
    					int v=q.remove();
    					for(w=firstArc(v);w>=0;w=nextArc(v,w)){           //对v的所有邻接点都进行判断是否已访问
    						if(vertexts[w].visit==false){
    							System.out.print(vertexts[w].data+" ");
    							vertexts[w].visit=true;
    							q.add(w);
    						}
    					}
    				}
    			}
    				
    		}
    		System.out.println();
    	}
    //转换成邻接矩阵
    	public void matrix(){
    		int max=999;             //初始值为无穷,用一个极大的数代替
    		int num=vertexts.length;
    		int m[][]=new int[num][num];
    		//初始化数组,值均为max
    		for(int i=0;i<num;i++){
    			for(int j=0;j<num;j++){
    				m[i][j]=max;
    			}
    		}
    		//赋值,将边的权重加入数组中
    		for(int i=0;i<num;i++){
    			Arc p=vertexts[i].firstArc;
    			while(p!=null){
    				m[i][p.adjVex]=p.weight;
    				p=p.nextArc;
    			}
    		}
    		//输出
    		System.out.println("矩阵表示法如下图:");
    		for(int i=0;i<num;i++){
    			System.out.print("  "+vertexts[i].data+"   ");
    		}
    		for(int i=0;i<num;i++){
    			System.out.println();
    			System.out.print(vertexts[i].data);
    			for(int j=0;j<num;j++){
    				if(m[i][j]==999){
    					System.out.print(" *    ");
    				}
    				else
    				System.out.print(" "+m[i][j]+"    ");
    			}
    		}
    		System.out.println();
    	}
    	//输出
    	public void printMatrix(){
    		matrix();
    		
    	}
    //逆	邻接表
    	public Ver[] inverse(){
    		int num=vertexts.length;
    		Ver inver[]=new Ver[num];                   //定义一个数组存放顶点
    		for(int i=0;i<num;i++){                     //将顶点存入数组
    			inver[i]=new Ver(vertexts[i].data);
    		}
    		for(int i=0;i<num;i++){                     //找到指向vertexts[i]的所有邻接点在数组中的位置,并将i封装到Arc中接到数组后边
    			Arc p=vertexts[i].firstArc;
    			while(p!=null){
    				Arc newArc=new Arc(i,p.weight);
    				newArc.nextArc=inver[p.adjVex].firstArc;
    				inver[p.adjVex].firstArc=newArc;
    			}
    		}
    		return inver;
    	}
    	
    //扩容
    		public void increaseSpace(int space){
    			Ver b[]=vertexts;
    			vertexts=new Ver[space];
    			for(int i=0;i<b.length;i++){
    				vertexts[i]=b[i];
    			}
    		}	
    //减小数组长度
    		public void reduceSpace(int space){
    			Ver b[]=vertexts;
    			vertexts=new Ver[space];
    			for(int i=0;i<space;i++){
    				vertexts[i]=b[i];
    			}
    		}	
    //增加顶点
    		public void addPoint(){
    			System.out.println("请输入要增加的顶点的个数");
    			int num=sc.nextInt();
    			int oldSize=vertexts.length;
    			int newSize=oldSize+num;     //增加后顶点总数
    			increaseSpace(newSize);      //扩容
    			System.out.println("请输入要增加的顶点");
    			for(int i=oldSize;i<newSize;i++){
    				int p=sc.nextInt();
    				vertexts[i]=new Ver(p);
    			}
    			System.out.println("添加成功!!!");
    		}
    //删除顶点
    		public void deletePoint(){
    			System.out.println("请输入要删除的顶点");
    			int n=sc.nextInt();
    			if(n>=vertexts.length)
    				System.out.println("要删除的顶点不存在");
    			
    			else{
    				for(int i=0;i<vertexts.length;i++){               //删除相关的边(以被删除顶点为弧头的边)
    		     		Arc p=vertexts[i].firstArc;
    		     	    while(p!=null){
    		     	    	if(p.adjVex==n){
    		     	    		deleteEdge(i,n);
    		     	    		break;
    		     	    	}
    		     	    	p=p.nextArc;
    		     	    }
    		    	}
    				
    			     for(int i=n;i<vertexts.length-1;i++){        //删除顶点
    				     vertexts[i]=vertexts[i+1];              //令被删除顶点后面的所有顶点前移,
    			      }  
    		     	reduceSpace(vertexts.length-1);
    		
    		     	 int w; 
    		     	 for(int i=0;i<vertexts.length;i++){          //调整顶点的邻接点
    		     		Arc p=vertexts[i].firstArc; 
    		     		while(p!=null){
    		     			if(p.adjVex>n){                       //邻接点的数据大于n,则减1
    		     				p.adjVex--;
    		     			}
    		     			p=p.nextArc;
    		     		} 	 
    			     }
    		     	
    		    	System.out.println("删除成功!!!");
    		    }
    		}
    		
    //增加边
    		public void addEdge(){
    			System.out.println("请输入要增加边");
    			int v=sc.nextInt();                          //弧尾
    			int w=sc.nextInt();                          //弧头
    			System.out.println("请输入要增加边的权");
    			int we=sc.nextInt();
    			Arc p=new Arc(w,we);
    			p.nextArc=vertexts[v].firstArc;
    			vertexts[v].firstArc=p;
    			System.out.println("添加成功!!!");
    		}
    //删除边
    		public void deleteEdge(){
    			System.out.println("请输入要删除的边");
    			int v=sc.nextInt();
    			int w=sc.nextInt();
    			deleteEdge(v,w);
    			System.out.println("删除成功!!!");
    		}
    		public void deleteEdge(int v,int w){
    			Arc p=vertexts[v].firstArc;
    			if(p.adjVex==w){              //是第一个邻接点
    				vertexts[v].firstArc=p.nextArc;
    			}
    			else{                                      //不是第一个邻接点
         			while(p.nextArc.adjVex!=w&&p.nextArc!=null){
         				p=p.nextArc;
         			}
         			p.nextArc=p.nextArc.nextArc;
         		}
    		}
    //判断是否为连通图
    		public void isLianTong(){
    			DFSTravel();
    			if(count==1)
    				System.out.println("该图为连通图");
    			else
    				System.out.println("该图不是连通图,连通分量个数为:"+count);
    			count=0;
    		}
    
    //广度优先生成树
    		public CSNode BFSTree(){
    			int w;
    			int n=0;             //判断是否已近存在一个根
    			CSNode rootNode=null;
    			Queue<Integer> q=new LinkedList<Integer>();
    			for(int i=0;i<vertexts.length;i++){    //令所有顶点的visit都为false
    				vertexts[i].visit=false;
    			}
    			CSNode node=new CSNode();
    			for(int i=0;i<vertexts.length;i++){
    				if(vertexts[i].visit==false){               //未被访问
    					vertexts[i].visit=true;
    					if(n==0){                              //还没有根,则该点作为根
    					    node=new CSNode(vertexts[i].data);
    					    rootNode=node;
    					}
    					if(n!=0){                                 //已经存在一个根,则该点作为根的兄弟
                               node.nextSibling=new CSNode(vertexts[i].data); 
                               node=node.nextSibling;
    					}
    					q.add(i);
    					while(!q.isEmpty()){
    						int v=q.remove();
    						for(w=firstArc(v);w>=0;w=nextArc(v,w)){
    							if(vertexts[w].visit==false){
    								if(node.firstChild==null)             //第一个孩子
    									node.firstChild=new CSNode(vertexts[w].data);
    								else{                                  //第一个孩子的兄弟
    									CSNode p=node.firstChild;
    									while(p.nextSibling!=null){
    										p=p.nextSibling;
    									}
    									p.nextSibling=new CSNode(vertexts[w].data);
    								}
    								vertexts[w].visit=true;
    								q.add(w);
    							}
    						}
    					}
    					n++;
    				}
    					
    			}
    			return rootNode;
    		}
    
    
    //层次非递归遍历
    		public void levelOrder(CSNode root){
    			int i=0;
    			Queue<CSNode> q=new LinkedList<CSNode>();
    			q.add(root);
    			while(q.isEmpty()!=true){
    				CSNode step=q.remove();
    				System.out.print(step.data);
    				if(step.firstChild!=null){
    					q.add(step.firstChild);
    				}
    				if(step.nextSibling!=null){
    					q.add(step.nextSibling);
    				}
    			}
    			System.out.println();
    		}
    //判断是否存在环  拓扑排序
    	    public void topSort(){
    	    	boolean flag=true;      //是否存在环的标志符
    	    	Queue<Integer> q=new LinkedList<Integer>();
    	    	for(int i=0;i<vertexts.length;i++){    //入度为0的点入队
    	    		if(vertexts[i].inDeg==0)
    	    			q.add(i);
    	    	}
    	   
    	    	while(!q.isEmpty()){
    	    		int w=0;
    	    		int v=q.poll();
    	    		for(w=firstArc(v);w>=0;w=nextArc(v,w)){
    	    			vertexts[w].inDeg--;              //与v相邻点的入度减1
    	    			if(vertexts[w].inDeg==0){
    	    				q.add(w);
    	    			}
    	    		}
    	    	}
    	    	
    	    	for(int i=0;i<vertexts.length;i++){      //若存在入度不为0的点,则存在环
    	    		if(vertexts[i].inDeg>0){
    	    			flag=false;
    	    			break;
    	    		}
    	    	}
    	    	if(flag==false)
    	    		System.out.println("存在环");
    	    	else
    	    		System.out.println("不存在环");
    	    	
    	    	
    	    }
    //Dijkstra算法
    	    public Ver Dijkstra(){
    	    	System.out.println("请输入起始点");
    	    	int s=sc.nextInt();
    	    	System.out.println("请输入起终点");
    	    	int e=sc.nextInt();
    	    	for(int i=0;i<vertexts.length;i++){   //初始化,dist为无穷
    	    		vertexts[i].known=false;
    	    		vertexts[i].dist=100;
    	    		vertexts[i].path=null;
    	    	}
    	    	vertexts[s].dist=0;              //令起点的dist为0
    	    	for(;;){
    	    		//找到未知点中dist为最小的顶点v	
    	    		Ver v=new Ver(100,-1);
    	    		for(int i=0;i<vertexts.length;i++){
    	    			if(vertexts[i].dist<v.dist&&vertexts[i].known==false){
    	    				v=vertexts[i];
    	    			}
    	    		}
    	    		if(v.data==-1)          //当所有顶点都访问过后退出
    	    			break;
    	    		v.known=true;
    	    		//对每一个与顶点v邻接的顶点w,依次判断v.dist+cv,w与w.dist的大小,更改w.dist的值
    	    		Arc w=v.firstArc;
    	    		while(w!=null){
    	    			if(vertexts[w.adjVex].dist>(v.dist+w.weight)&&vertexts[w.adjVex].known==false){           //w.dist与v.dist+w.weight 比较,确定w.dist
    	    				vertexts[w.adjVex].dist=v.dist+w.weight;
    	    				vertexts[w.adjVex].path=v;
    	    			}
    	    			w=w.nextArc;
    	    		}
    	    	}
    	    	return vertexts[e];
    	    }
    	    public void printpath(Ver v){
    	    	if(v.path!=null){
    	    		printpath(v.path);
    	    		System.out.print("to");
    	    	}
    	    	System.out.print(v.data);
    	    }
    //Floyd算法
    	    //核心
    	    public int[][] floyd(){
    	    	int num=vertexts.length;
    		    int d[][]=new int[num][num];
    	    	int e[][]=new int[num][num];   //存放最短路径
    	    	int max=999;
    	    	//定义n阶矩阵D,存储初始两个顶点之间的距离
    	    	for(int i=0;i<num;i++){                  //初始值为无穷,对角线为0
    	    		for(int j=0;j<num;j++){
    	    			if(i==j)
    	    				d[i][j]=0;
    	    			d[i][j]=max;
    	    			e[i][j]=0;
    	    		}
    	    	}
    	    	for(int i=0;i<num;i++){               //将路径长加入到d中
    				Arc p=vertexts[i].firstArc;
    				while(p!=null){
    					d[i][p.adjVex]=p.weight;
    					p=p.nextArc;
    				}
    			}
    	    	
    	    	//由D(k-1)生成新的矩阵D(k),表示任意2个顶点之间最短路径的长度,
    	    	int k=0,i=0,j=0;
    	    	for(k=0;k<num;k++)
    	    		for(i=0;i<num;i++)
    	    			for(j=0;j<num;j++){
    	    				if(d[i][k]+d[k][j]<d[i][j]){
    	    					d[i][j]=d[i][k]+d[k][j];
    	    					e[i][j]=k;
    	    				}
    	    			}
    	    	for(int a=0;a<num;a++)                //令e中没有路径的两顶点为max
    	    		for(int b=0;b<num;b++){
    	    			if(d[a][b]==max&&d[b][a]==max&&e[a][b]==0){
    	    				e[a][b]=999;
    	    				e[b][a]=999;
    	    			}
    	    		}
    	    	return e;
    	    }
    	    String path="";
    	    //获取路径
    	    public String path(int i,int j,int e[][]){
    	    	int k=e[i][j];
    	    	if(k==999)              
    	    		return "can't";//不存在路径
    	    	if(k==0)
    	    		return path;
    	    	path(i,k,e);
    	    	path+="to"+vertexts[k].data;
    	    	return path(k,j,e);
    	    }
    	    public void Floyd(){
    	    	System.out.println("请输入顶点和终点");
    	    	int begin=sc.nextInt();
    	    	int end=sc.nextInt();
    	    	System.out.println(vertexts[begin].data+"到"+vertexts[end].data+"的路径为"+vertexts[begin].data+path(begin,end,floyd())+"to"+vertexts[end].data);
    	    	
    	    }
    	    
    //判断是否存在路径
    	    public void isPath(){
    	    	System.out.println("请输入两个顶点");
    			int v=sc.nextInt();
    			int w=sc.nextInt();
    			String path=path(v,w,floyd());
    			if(path.equals("can't"))
    				System.out.println(vertexts[v].data+"和"+vertexts[w].data+"之间不存在路径");
    			else
    			  System.out.println(vertexts[v].data+"和"+vertexts[w].data+"之间存在路径");
    	    }
    
    	    
    	    
    //菜单
    	    public void menu(){
    	    	System.out.println("1:创建有向网");
    	    	System.out.println("2:增加顶点");
    	    	System.out.println("3:删除顶点");
    	    	System.out.println("4:增加边");
    	    	System.out.println("5:删除边");
    	    	System.out.println("6:DFS");
    	    	System.out.println("7:BFS");
    	    	System.out.println("8:判断是否存在路径");
    	    	System.out.println("9:转成邻接矩阵,并输出   ");
    	    	System.out.println("10:BFS生成树");
    	    	System.out.println("11:Dijkstra算法");
    	    	System.out.println("12:floyd算法");
    	    	System.out.println("13:判断是否存在环");
    	    	System.out.println("14:判断是否是连通图");
    	    	System.out.println("0:退出");
                System.out.println("***********************************");    
    	    }
    	    public void choice(){
                System.out.println("请输入您的要进行的操作:");
            }
    	    
    	    
    	public static void main(String[] args) {
    		DiNet d=new DiNet();	
    		Scanner sc=new Scanner(System.in);
    		d.menu();
    		boolean flag=true;
    		while(flag){
    			d.choice();
    			int c=sc.nextInt();
    			switch(c){
    			case 0: flag=false;
    			case 1: d.creatNet();     break;
    			case 2: d.addPoint();     break;
    			case 3: d.deletePoint();  break;
    			case 4: d.addEdge();      break;
    			case 5: d.deleteEdge();   break;
    			case 6: d.DFSTravel();    break;
    			case 7: d.BFS();          break;
    			case 8: d.isPath();       break;
    			case 9: d.matrix();       break;
    			case 10: d.levelOrder(d.BFSTree());   break;
    			case 11: d.printpath(d.Dijkstra());  break;
    			case 12: d.Floyd();                  break;
    			case 13: d.topSort();                break;
    			case 14: d.isLianTong();                break;
    			default :System.out.println("您输错了,请重新输入");
    			} 
    			
    		}
    		
    	/*实例:	
    	        0 1 2
    		    0 3 1
    		    1 3 3
    		    1 4 10
    		    2 0 4 
    		    2 5 5 
    		    3 2 2 
    		    3 4 2 
    		    3 5 8 
    		    3 6 4 
    		    4 6 6 
    		    6 5 1
    		    */
    		/*0 1 1
    		1 3 1
    		3 7 1
    		4 1 1
    		4 7 1
    		0 2 1
    		2 5 1
    		2 6 1
    		5 6 1*/
    	
    	}
    
    }
    


     

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    获取资源文件 r.drawable中的图片转换为drawable、bitmap
    Android 启动白屏或者黑屏闪现解决
    Android应用截图方法
    史上最全的变量、作用域和内存问题
    RunLoop总结:RunLoop的应用场景(四)
    poj3436 ACM Computer Factory, 最大流,输出路径
    android开发——从相冊中选择图片不裁剪
    <html>
    poj3073
    poj 2482 Stars in Your Window (线段树扫描线)
  • 原文地址:https://www.cnblogs.com/dingxiaoyue/p/4931849.html
Copyright © 2011-2022 走看看