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*/
    	
    	}
    
    }
    


     

  • 相关阅读:
    9.11 eventbus
    9.10,,,实现new instanceof apply call 高阶函数,偏函数,柯里化
    9.9 promise实现 写完了传到gitee上面了,这里这个不完整
    9.5cors配置代码
    9.5 jsonp 实现
    9.5 http tcp https总结
    9.3 es6 class一部分 and es5 class 发布订阅
    8.30 cookie session token jwt
    8.30vue响应式原理
    warning: LF will be replaced by CRLF in renard-wx/project.config.json. The file will have its original line endings in your working directory
  • 原文地址:https://www.cnblogs.com/oversea201405/p/3752234.html
Copyright © 2011-2022 走看看