亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? graphtheory.java

?? 用Java開發的實用數學建模程序 簡單易懂 初學者可以用來學習java知識
?? JAVA
字號:
/*
 *@(#)GraphTheory.java 2.0 2005/05/02
 *
 *清華大學 精密儀器與機械學系
 *范燦升 fancansheng@163.com
 */

package algorithm;

import java.util.*;

import algorithm.HamiltonSort;
import ADT.BinaryTree;

/**
 *這個類是圖論的類,里面包含一些圖論常見的算法。
 *@version	2.0, 2005/04/30
 *@author	范燦升
 *@see	Modeling
 *@see	input.GraphInput
 */

public class GraphTheory
{
	private int[][] adjacentMatrix;//鄰接矩陣
	private int[][] incidenceMatrix;//關聯矩陣
	private int[][] weightMatrix;//權矩陣
	private int matrixType;//構造時矩陣的類型
	
	/**
	 *說明構造方法所傳過來的矩陣是鄰接矩陣。
	 */
	public final static int ADJACENT=1;
	
	/**
	 *說明構造方法所傳過來的矩陣是關聯矩陣。
	 */
	public final static int INCIDENCE=2;
	
	/**
	 *說明構造方法所傳過來的矩陣是權矩陣。
	 */
	public final static int WEIGHT=3;
	
	/**
	 *圖的結點數。
	 */
	public int n;
	
	/**
	 *圖的邊數。
	 */
	public int m;
	
	/**
	 *用所給矩陣生成一個圖。
	 *@param	matrix		圖所對應的矩陣,這個矩陣在GraphTheory類中產生克隆副本,GraphTheory的成員方法不會對該矩陣生產影響。
	 *@param	matrixType	矩陣類型,可以為{@link #ADJACENT}、{@link #INCIDENCE}、{@link #WEIGHT}。
	 */
	public GraphTheory(int[][] matrix,int matrixType)
	{
		this.matrixType=matrixType;
		switch(matrixType)
		{
			case ADJACENT:
				adjacentMatrix=(int[][])matrix.clone();
				break;
			case INCIDENCE:
				incidenceMatrix=(int[][])matrix.clone();
				break;
			case WEIGHT:
				weightMatrix=(int[][])matrix.clone();
				break;
		}
	}
	
	/**
	 *Dijkstra算法,根據權矩陣計算圖中任意兩結點間的最短路。
	 *<p>計算最短路的圖必須是正權有向圖。
	 *<p>受int大小的限制,權值必須小于Integer.MAX_VALUE,即2147483647。
	 *對于無向圖,用戶必須先把它的權矩陣轉換成有向圖的權矩陣。
	 *@param	start	開始結點,結點編號從0開始
	 *@param	end		結束結點,結點編號從0開始
	 *@return	Vector類的一個實例,該Vector中只有三個元素,int[]、Integer及int[]的實例。
	 *			<p>其中第一int[]是從start結點到任一結點的最短路徑矩陣path,int[end]中所存放的是從start到end的最短路徑中end的前一結點。
	 *			<p>Integer是最短路徑的長度的整型數封裝。當Integer為-1時,說明不存在從start到end的路徑。
	 *			<p>第二個int[]是從start到各結點(包括自身)的最短路徑長度len,上面的Integer就是對int[]中第end個元素的封裝。
	 *			如果Integer為-1,則len中部分元素還保持初值Integer.MAX_VALUE。
	 *			<p>如果構造該類時的矩陣不是權矩陣,或者不是圖不是正權圖,則返回null。
	 */
	public Vector dijkstra(int start,int end)
	{
		int i,j;//循環變量
		int ii,jj;//算法中用
		int min;
		int count;//計算下面的undetermined數組中還有多少元素為true
		int lastCount=-1;//賦值為-1,下面if語句的lastCount==count第一次就肯定不會滿足
		boolean done;//用于檢查是否可以跳出算法中的循環
		n=weightMatrix.length;
		if(matrixType!=WEIGHT)
			return null;
		//不是權矩陣就返回null
		
		n=weightMatrix.length;
		for(i=0;i<n;i++)
		{
			for(j=0;j<n;j++)
			{
				if(weightMatrix[i][j]<0)
					return null;
			}
		}
		//如果權矩陣含有小于0的元素就返回null
		
		int[] path=new int[n];
		int[] len=new int[n];
		for(i=0;i<n;i++)
			path[i]=start;
		for(j=0;j<n;j++)
		{
			if(weightMatrix[start][j]>0)//從start結點到j有道路
				len[j]=weightMatrix[start][j];
			else
				len[j]=Integer.MAX_VALUE;
		}
		len[start]=0;//從start到start的長度當然為0
		
		boolean[] undetermined=new boolean[n];
		//true表示還沒有找到最短路
		for(i=0;i<n;i++)
			undetermined[i]=true;
		undetermined[start]=false;
		//初始化
		
		jj=start;
		while(true)
		{
			min=Integer.MAX_VALUE;
			for(ii=0;ii<n;ii++)
			{
				if(undetermined[ii]==true)
				{
					if(len[ii]<min)
					{
						jj=ii;
						min=len[ii];
					}
				}
			}
			//尋找len[ii]的最小值,并對取最小值時的ii用jj標記
			undetermined[jj]=false;
			
			done=true;
			count=0;
			for(i=0;i<n;i++)
			{
				if(undetermined[i]==true)
				{
					done=false;//undetermined中還有數,不能跳出while循環
					count++;
				}
			}
			if(lastCount==count)
			//兩次undetermined中為true的元素數目相等,說明下面的for循環什么不起作用,不存在start到end的路徑
				break;
			lastCount=count;
			if(done==true)
				break;
			//判斷是否可以跳出while循環
			
			for(i=0;i<n;i++)
			{
				if((weightMatrix[jj][i]>0)&&(undetermined[i]==true))
				//jj的后繼結點,且在undetermined中
				{
					if(len[i]>len[jj]+weightMatrix[jj][i])
					{
						len[i]=len[jj]+weightMatrix[jj][i];
						path[i]=jj;
					}
				}
			}//len[jj]始終不是Integer.MAX_VALUE
		}
		//完成算法的主體部分
		
		//現在len和path都有了,可以進行封裝和返回了
		if(len[end]==Integer.MAX_VALUE)
			len[end]=-1;
		Integer solutionLength=new Integer(len[end]);
		Vector vector=new Vector();
		vector.add(path);
		vector.add(solutionLength);
		vector.add(len);
		return vector;
	}
	
	
	/**
	 *用分支與界法求解旅行商問題。
	 *<p>計算旅行商問題的圖必須是無向完全圖。由于無向圖的權矩陣是對稱陣,因此該方法不檢查權矩陣是否真的為對稱陣,
	 *而是直接使用權矩陣對角線以上的元素,對權矩陣對稱性的檢查就在輸入端完成。
	 *<p>圖的結點數不能小于3。
	 *<p>受int大小的限制,權值必須小于Integer.MAX_VALUE,即2147483647。
	 *@return	整型數組int[],其中int[].length==n+1,int[0]是哈密頓圈的長度,從int[1]到int[n]記錄哈密頓圈依次經過的結點。
	 *			結點從0從開始。
	 *			<p>以下三種情況返回null:該圖不是完全圖、結點數小于3、構造GraphTheory類時matrixType不為WEIGHT。
	 */
	public int[] hamilton()
	{
		int i,j,k;
		n=weightMatrix.length;
		if((n<3)||(matrixType!=WEIGHT))
			return null;
		int[][] edge=new int[(n*n-n)/2][5];
		//邊集合,每條邊包含五個元素,分別為邊權、結點、結點、索引、由邊生成路徑時是否已作標記
		k=0;
		for(i=0;i<n;i++)
		{
			for(j=i+1;j<n;j++)
			{
				if(weightMatrix[i][j]==0)
					return null;
				edge[k][0]=weightMatrix[i][j];
				edge[k][1]=i;
				edge[k][2]=j;
				edge[k][4]=0;//未取該邊
				k++;
			}
		}
		//檢查是否為完全圖,同時完成對待排序邊集合的初始化
		
		Arrays.sort(edge,new HamiltonSort());
		for(i=0;i<edge.length;i++)
			edge[i][3]=i;//為edge設置索引位,即排好序后在隊列中的順序
		int len=Integer.MAX_VALUE;
		//排序,設置索引和置初始邊界
		
		int[][] stack=new int[n][5];//用來存放棧中的邊
		int currentLength=0;
		int popCount;
		int[] nodeCount=new int[n];//標記各結點出現的次數
		for(i=0;i<n;i++)
			nodeCount[i]=0;
		for(i=0;i<n;i++)
		{
			stack[i]=edge[i];
			currentLength+=edge[i][0];
		}
		for(i=0;i<n;i++)
		{
			nodeCount[stack[i][1]]++;
			nodeCount[stack[i][2]]++;
		}
		popCount=n;//popCount是從后面數起索引連續的元素的個數
		
		int index;
		boolean cycled;//判斷是否構成哈密頓圈
		int[][] result=new int[n][5];//記錄最終結果
		while(true)
		{
			cycled=true;
			for(i=0;i<n;i++)
			{
				if(nodeCount[i]!=2)
				{
					cycled=false;
					break;
				}
			}
			
			if(cycled&&(currentLength<len)&&(popCount!=n))
			//stack中的元素構成哈密頓圈且該圈長度比原來的圈小,同時stack還可以往后退
			{
				len=currentLength;
				for(k=0;k<n;k++)
					result[k]=stack[k];
				index=stack[n-1-popCount][3]+1;//后面連續在stack中的前一位的下一個索引
				for(j=n-1-popCount;j<n;j++)
				//開始新分支
				{
					if(index>=edge.length)
						break;//不能再退就返回
					
					currentLength-=stack[j][0];
					nodeCount[stack[j][1]]--;
					nodeCount[stack[j][2]]--;
					
					stack[j]=edge[index];
					//stack[j]已被它對應的edge后面的邊替換
					index++;
					
					currentLength+=stack[j][0];
					nodeCount[stack[j][1]]++;
					nodeCount[stack[j][2]]++;
				}
			}
			else if(cycled&&(currentLength<len)&&(popCount==n))
			//當stack不能往后退時
			{
				len=currentLength;
				for(k=0;k<n;k++)
					result[k]=stack[k];
				break;
			}
			else if(currentLength>=len)
			//長度比界限大也要開始新分支
			{
				index=stack[n-1-popCount][3]+1;
				for(j=n-1-popCount;j<n;j++)
				//開始新分支
				{
					if(index>=edge.length)
						break;
					
					currentLength-=stack[j][0];
					nodeCount[stack[j][1]]--;
					nodeCount[stack[j][2]]--;
					
					stack[j]=edge[index];
					//stack[j]已被它對應的edge后面的邊替換
					index++;
					
					currentLength+=stack[j][0];
					nodeCount[stack[j][1]]++;
					nodeCount[stack[j][2]]++;
				}
			}
			else
			//相當于else if((!cycled)&&(currentLength<len))
			//長度比界限小,同時不構成哈密頓圈,可以繼續向下搜
			{
				for(i=0;i<n;i++)
				//從stack最后一個元素起,依次往edge后面退,只要有一個可退就中斷
				{
					if(stack[n-1-i][3]<(edge.length-1-i))//防止已經有元素退到edge的最后
					{
						currentLength-=stack[n-1-i][0];
						nodeCount[stack[n-1-i][1]]--;
						nodeCount[stack[n-1-i][2]]--;
						
						index=stack[n-1-i][3];
						index++;
						stack[n-1-i]=edge[index];
						
						currentLength+=stack[n-1-i][0];
						nodeCount[stack[n-1-i][1]]++;
						nodeCount[stack[n-1-i][2]]++;
						
						break;
					}
				}
			}
			
			popCount=1;
			for(i=n-1;i>0;i--)
			//更新popCount
			//由于是和stack[i]的前一個比較,所以i不能為0
			{
				if(stack[i][3]==(stack[i-1][3]+1))//連續
					popCount++;
				else
					break;//不馬上跳出循環的話popCount的記錄就不準
			}
			
			if((popCount==n)&&(len<Integer.MAX_VALUE))
				break;//全部連續,剩下的分支只會比len大,可以跳出循環
		}
		//完成主體算法
		//stack中的元素就是構成最小哈密頓圈的邊
		
		
		int[] path=new int[n+1];
		path[0]=len;
		path[1]=result[0][1];
		for(i=1;i<path.length-1;i++)
		{
			for(j=0;j<result.length;j++)
			{
				if(result[j][1]==path[i]&&result[j][4]==0)
				{
					path[i+1]=result[j][2];
					result[j][4]=1;
					break;
				}
				if(result[j][2]==path[i]&&result[j][4]==0)
				{
					path[i+1]=result[j][1];
					result[j][4]=1;
					break;
				}
			}
		}
		return path;
		//生成路徑并返回
	}
	
	/**
	 *Huffman算法,根據所給樹的結點鏈表對構造Huffman樹的過程作一次遞歸。
	 *<p>構造的過程是把權最小的兩個結點合并為一個結點。
	 *@param	binTree	等待構樹的結點鏈表。
	 *			<p>最終得到的binTree是這樣一個鏈表:該鏈表中只有一個元素,為Huffman樹的根結點,是一個二叉樹結點類,
	 *			根據該根結點,可以找到二叉樹的全部結點。
	 *			<p>需要注意的是:生成Huffman樹的過程是對方法自身的不斷遞歸調用,
	 *			因此得到的BinaryTree中的info域并未被初始化。
	 *			<p>要得到含有路徑信息的Huffman樹,應調用huffman方法。
	 *@see	#huffman
	 *@see	#generateHuffmanPath
	 */
	public static void generateHuffmanTree(LinkedList binTree)
	{
		if(binTree.size()==1)
			return;
		else
		{
			Collections.sort(binTree,new BinaryTreeSort());
			BinaryTree tempLeft=(BinaryTree)binTree.removeFirst();
			BinaryTree tempRight=(BinaryTree)binTree.removeFirst();
			BinaryTree tempParent=new BinaryTree();
			
			tempParent.leftChild=tempLeft;
			tempParent.rightChild=tempRight;
			tempParent.weight=tempLeft.weight+tempRight.weight;
			tempLeft.parent=tempParent;
			tempRight.parent=tempParent;
			
			binTree.addFirst(tempParent);
			generateHuffmanTree(binTree);
		}
	}
	
	/**
	 *根據已生成的Huffman樹生成樹中各結點的路徑。
	 *<p>由于Huffman樹是二叉樹,因此用0和1表示從根結點到當前結點的路徑,
	 *0表示從父結點向左走得到下一結點,1表示從父結點向右走得到下一結點。
	 *@param	currentNode	當前結點
	 *@see	#huffman
	 *@see	#generateHuffmanTree
	 */
	public static void generateHuffmanPath(BinaryTree currentNode)
	{
		if(currentNode.leftChild==null && currentNode.rightChild==null)
			return;
		else
		{
			currentNode.leftChild.info=new StringBuffer(currentNode.info.toString());
			currentNode.leftChild.info.append("0");
			generateHuffmanPath(currentNode.leftChild);
			
			currentNode.rightChild.info=new StringBuffer(currentNode.info.toString());
			currentNode.rightChild.info.append("1");
			generateHuffmanPath(currentNode.rightChild);
		}
	}
	
	/**
	 *Huffman算法,根據所給樹葉結點的權構造最優二叉樹,該樹稱為Huffman樹。
	 *@param	leafVertex	樹葉結點的權數組
	 *@return	Huffman樹的樹葉結點數組,每個結點中都含有從根到該樹葉結點的路徑。
	 *			<p>0表示向左,1表示向右。
	 *@see	#generateHuffmanTree
	 *@see	#generateHuffmanPath
	 */
	public static BinaryTree[] huffman(int[] leafVertex)
	{
		int n=leafVertex.length;
		int i;
		BinaryTree[] binTree=new BinaryTree[n];
		LinkedList binTreeList=new LinkedList();
		for(i=0;i<n;i++)
		{
			binTree[i]=new BinaryTree();
			binTree[i].weight=leafVertex[i];
			binTree[i].id=i;
			binTreeList.add(binTree[i]);
		}
		
		generateHuffmanTree(binTreeList);
		BinaryTree root=(BinaryTree)binTreeList.get(0);
		root.info=new StringBuffer();
		generateHuffmanPath(root);
		return binTree;
	}
}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
有码一区二区三区| 久久久久久久久免费| 久久久国际精品| 91久久国产最好的精华液| 日韩激情一区二区| 国产精品国产三级国产普通话99 | 91精品午夜视频| 日本黄色一区二区| eeuss鲁片一区二区三区在线观看| **欧美大码日韩| 精品国产一区二区三区久久久蜜月| 日本韩国精品在线| 91丨porny丨中文| 国产伦精品一区二区三区免费| 亚洲一二三四在线| 国产欧美精品一区| 国产日产欧产精品推荐色| 日韩欧美视频在线| 91精品欧美久久久久久动漫| 色婷婷一区二区三区四区| 99久久久免费精品国产一区二区 | 成人教育av在线| 国产成人综合精品三级| 国产精品亚洲人在线观看| 国产成人福利片| 91丨porny丨最新| 欧美日韩成人综合天天影院 | 日本不卡1234视频| 日韩不卡免费视频| 精品一区二区综合| 国产成人午夜99999| 成人性色生活片| 日韩欧美久久久| 精品国产人成亚洲区| 欧美三级乱人伦电影| av在线不卡免费看| 91丨porny丨在线| 欧美性三三影院| 日韩精品一区二区在线观看| 亚洲成av人片观看| 亚洲精品午夜久久久| 亚洲欧洲韩国日本视频| 日韩欧美的一区二区| 色综合久久中文字幕| 色噜噜夜夜夜综合网| 在线不卡a资源高清| 国产精品看片你懂得| 免费高清在线视频一区·| 国产99久久久久| 一本色道a无线码一区v| 久久久三级国产网站| 香蕉av福利精品导航 | 久久99精品久久久久婷婷| 99精品在线免费| www激情久久| 全国精品久久少妇| 在线亚洲+欧美+日本专区| 国产精品久久三| 国产91精品精华液一区二区三区| 在线观看免费成人| 日本一区二区在线不卡| 午夜精品久久久久久久久久久| 国产寡妇亲子伦一区二区| 欧美大片一区二区三区| 日日噜噜夜夜狠狠视频欧美人| 色综合天天综合狠狠| 综合色中文字幕| 不卡一区二区中文字幕| 国产精品久久一卡二卡| 91农村精品一区二区在线| 中文字幕亚洲精品在线观看| 99久久精品国产观看| 亚洲国产精品黑人久久久| 首页国产丝袜综合| 日韩一区二区三区免费看 | 99re成人在线| 亚洲高清在线精品| 日韩一区二区三区电影在线观看| 琪琪久久久久日韩精品| 精品乱码亚洲一区二区不卡| 国产精品资源在线| 一二三区精品视频| 久久夜色精品一区| 91网页版在线| 久久99这里只有精品| 精品福利在线导航| 91麻豆高清视频| 麻豆精品精品国产自在97香蕉 | 欧美在线制服丝袜| 久久99国产精品久久99果冻传媒| 亚洲婷婷综合色高清在线| 欧美精品少妇一区二区三区| 国产一区二区在线视频| 亚洲一区二区三区视频在线| 日韩午夜激情视频| 欧美中文字幕一区| 成人av网站免费观看| 久久精品999| 日韩精彩视频在线观看| 亚洲免费av观看| 欧美r级电影在线观看| 在线观看日韩精品| 94-欧美-setu| 99视频精品在线| 国模套图日韩精品一区二区| 丝袜诱惑亚洲看片| 亚洲制服丝袜一区| 亚洲综合在线视频| 亚洲一区二区欧美激情| 一区二区三区在线播放| 亚洲精品视频在线观看免费| 综合久久综合久久| ●精品国产综合乱码久久久久| 国产欧美日韩另类视频免费观看| 日韩精品一区国产麻豆| 日韩精品一区二区三区中文精品| 亚洲精品在线三区| 一区二区三区在线视频免费观看| 中文字幕av一区二区三区高| 国产精品水嫩水嫩| 亚洲裸体在线观看| 午夜精品久久久久久久 | 国产在线看一区| av爱爱亚洲一区| 欧美午夜精品一区二区蜜桃| 欧美午夜一区二区三区| 成人手机在线视频| 欧美性色综合网| 亚洲精品高清在线| 国产高清成人在线| 26uuu亚洲综合色欧美| 亚洲成人自拍网| 91福利精品第一导航| 欧美国产激情一区二区三区蜜月| 亚洲一区国产视频| 99视频在线观看一区三区| 久久久精品影视| 国产黄色精品视频| 国产日韩欧美高清| 国产成人av在线影院| 国产女人18水真多18精品一级做 | 粉嫩久久99精品久久久久久夜| 欧美一区二区啪啪| 久热成人在线视频| 久久综合久久综合亚洲| 国产乱码精品一区二区三区av | 亚洲激情六月丁香| 欧美日韩dvd在线观看| 午夜欧美2019年伦理| 日韩精品一区二区在线| 国产福利电影一区二区三区| 国产午夜精品一区二区三区视频| 国产精品一区二区免费不卡 | 亚洲色图19p| 欧美中文字幕久久| 日韩不卡手机在线v区| 26uuu国产电影一区二区| 99久久婷婷国产综合精品电影| 一区二区三区丝袜| 日韩精品一区二区三区蜜臀| 裸体健美xxxx欧美裸体表演| 欧美熟乱第一页| 国产成人啪免费观看软件| 亚洲人亚洲人成电影网站色| 91麻豆免费看| 国产一区二区三区免费| 一区二区三区四区激情| 日本一区二区三区高清不卡| 欧美伊人久久久久久久久影院| 国产资源精品在线观看| 亚洲国产精品自拍| 中文字幕在线观看一区| 久久色在线观看| 欧美一卡二卡三卡四卡| 欧美日韩一区 二区 三区 久久精品| 国产一区视频导航| 免费一区二区视频| 亚洲少妇30p| 国产精品18久久久久久久久 | 91美女片黄在线| 国产精品99精品久久免费| 美洲天堂一区二卡三卡四卡视频 | 国产99久久精品| 精品影视av免费| 国产成a人亚洲| 国产91精品一区二区| 懂色av一区二区夜夜嗨| 国产精品88av| 国产成人午夜片在线观看高清观看| 日本sm残虐另类| 老司机精品视频线观看86| 久久超碰97人人做人人爱| 精品一区免费av| 不卡在线观看av| 欧美性大战xxxxx久久久| 欧美色综合网站| 7777精品伊人久久久大香线蕉| 欧美一区二区三级| 国产精品天干天干在观线| 欧美国产成人精品|