當前位置:首頁 » 操作系統 » javadijkstra演算法

javadijkstra演算法

發布時間: 2023-02-14 03:01:48

java中最短路徑演算法

給你個算graph上最短路徑的比較流行的方法

Algorithm Dijkstra(V, E, cost, s)
T ;
Cost(V[s]) 0
Prev(V[s]) none
for i 0 to length[V] - 1 do
if (i 6= s) then
Cost(V[i]) +1
Prev(V[i]) none
Build heap NotInTree from V
for i 1 to length[V] do
u DeleteMin(NotInTree)
add (u, Prev(u)) to T
for each neighbor v of u do
if (Cost(v) > Cost(u) + cost(u,v)) then
Cost(v) Cost(u) + cost(u,v)
Prev(v) u
return T

Ⅱ 題目1:一個簡單的演算法演示程序(JAVA語言實現)

1. 選擇一個演算法(提供選擇見下),利用各種方法(圖形、動畫等)演示演算法的演示過程。
2. 可以進行手動演示,也可以自動步進式演示。
3. 允許用戶設置演算法的各個輸入參數,以及自動步進式演示中的時間間隔。
4. 不同的演算法輸入要求見下。
界面要求:
1. 盡量使用圖形界面實現,要符合日常軟體使用規范來設計菜單和界面。
2. 如果無法實現圖形界面,則在命令行方式下也需要提供菜單,方便用戶操作。
其他要求:
1. 標識符命名遵循Windows命名規范。
2. 能夠注意各種異常處理,注重提高程序運行效率。
提交內容:
1. 全部源代碼。
2. 軟體設計和使用說明書(UML類圖;實現的功能、主要技術;使用幫助文檔)
參考演算法:
1. 最小生成樹演算法:Prim演算法、Kruskal演算法。允許以下方式輸入一個圖形:繪制圖形、輸入鄰接矩陣、輸入邊及其關聯的頂點。要求在圖形方式下進行演示演算法執行步驟。
2. 單源最短路演算法:Dijkstra演算法。允許以下方式輸入一個圖形:繪制圖形、輸入鄰接矩陣、輸入邊及其關聯的頂點。要求在圖形方式下進行演示演算法執行步驟。
3. 最優編碼演算法:Huffman編碼演算法。允許用戶輸入一段英文文字,或者打開一個txt文檔(英文內容),據此文檔內容進行編碼。要求動態列出每個字元的出現概率統計結果以及對應編碼。
4. 其他可供演示的具有一定難度的演算法,如關鍵路徑問題、有向圖的極大連通分支等。

Ⅲ 求數據結構公交線路咨詢的代碼用java,其中求最短路徑用Floyd演算法

不知道你想怎麼搞 反正感覺A*演算法也可以,網上一大堆,還有就是Dijkstra演算法

Ⅳ 求大佬用java幫我實現dijkstra演算法,單源最短路徑

python">

import heapq
from collections import defaultdict
edges = [["A","B"],["A","D"],["A","E"],["B","C"],["C","E"],["D","E"],["D","C"]]
dist = [10,30,100,50,10,60,20]
res = []
def dijkstra(e,dist,start,end):
‍ hm = defaultdict(list)
‍ for i in range(len(e)):
‍ ‍ hm[e[i][0]].append((e[i][1],dist[i]))
‍ r = {}
‍ r[start] = 0
‍ q = [(0,start,[start])]
‍ while q:
‍ ‍ dis,node,res = heapq.heappop(q)
‍ ‍ if node == end:
‍ ‍ ‍ return dis,res
‍ ‍ for u,v in hm[node]:
‍ ‍ ‍ t = dis+v
‍ ‍ ‍ if u not in r or t < r[u]:
‍ ‍ ‍ ‍ r[u] = t
‍ ‍ ‍ ‍ heapq.heappush(q,(t,u,res+[u]))
‍ return 0,[]
dijkstra(edges,dist,"A","E")

Ⅳ webService 請求報錯: Caused by: java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSD

Java最新帖子JAVA GC 機制詳解fastjson獲取unknown的欄位150. Evaluate Reverse Polish NotationJAVA 常用集合內部機制原理OWNER支持配置文件目錄的繼承ThreadPoolExecutor策略配置以及應用場景通過maven管理不同環境下的配置文件MyBatis 基本用法NumberPicker實現滑動選擇MyBatis 使用annonation定義類型映射Java熱門帖子Android入門簡單實例Android中Socket通信的實現方法概述模擬列印機排隊列印效果Java設計模式之責任鏈模式簡介實例解讀Ajax與servlet交互的方法java壓縮zip文件中文亂碼問題解決方法基於Java實現的Dijkstra演算法示例JAVA中使用雙括弧來初始化靜態常量的小技巧Java8新特性之重復註解(repeating annotations)淺析Jedis出現connection timeout問題解決方法(JedisPool連接池使用實例)

Ⅵ 一個有關於java的演算法問題,求高手協做

//參考別人的,自己就懶得寫了,你拿去參考參考...

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Dijkstra {
private int[][] graph;// 加權有向圖
private int start;// 源點編號 從 0開始
private int dimention;
static int INF = Integer.MAX_VALUE / 100;
// 用於標記頂點是否已經計算
private Set<Integer> vertexSet = new HashSet<Integer>();
// 存儲結果,Map的key對應各終點編號,value對應路徑編號列表。
private Map<Integer, List<Integer>> pathListMap = new HashMap<Integer, List<Integer>>();

public Dijkstra(int[][] graph, int start) {
this.graph = graph;
this.start = start;
this.dimention = graph.length;
calculate();
}

private void calculate() {
// 初始化
for (int end = 0; end < dimention; end++) {
if (end == start) {
continue;
}// 起始點自己的路徑排除。
List<Integer> pathList = new ArrayList<Integer>();
pathList.add(start);// 每條路徑的起始點都為start,pathList只記錄編號,不記錄路徑權值
pathList.add(end);// 每條路徑的第二個參數為終點編號
pathListMap.put(end, pathList);
}
// 計算主體
for (int bridge = 0; bridge < dimention; bridge++) {
if (bridge == start) {
continue;
}
if (!vertexSet.contains(bridge)) {// 確保每個基點只循環計算一次
for (int next = 0; next < dimention; next++) {
if (next == start || next == bridge) {
continue;
}
if (startTo(bridge) + getRawLength(bridge, next) < startTo(next)) {
List<Integer> pathList = pathListMap.get(next);
List<Integer> bridgePathList = pathListMap.get(bridge);
// 清空,使用新的
pathList.clear();
pathList.addAll(bridgePathList);
pathList.add(next);
}
}
}
vertexSet.add(bridge);
}
// 檢查,是否橋接的路徑都被更新
for (int end = 0; end < dimention; end++) {
if (end == start) {
continue;
}
List<Integer> pathList = pathListMap.get(end);
int size = pathList.size();
if (size > 2) {
for (int end2 = 0; end2 < dimention; end2++) {
int isEnd = pathList.get(size - 2);
if (end2 == isEnd) {
pathList.clear();
pathList.addAll(pathListMap.get(end2));
pathList.add(end);
}
}
}
}
}

private int startTo(int end) {
int pathLen = 0;
List<Integer> pathList = pathListMap.get(end);
for (int i = 0; i < pathList.size() - 1; i++) {
pathLen += graph[pathList.get(i)][pathList.get(i + 1)];
}
return pathLen;
}

private int getRawLength(int start, int end) {
if (end == start) {
return 0;
}
return graph[start][end];
}

public int getLength(int end) {
if (end == start) {
return 0;
}
return startTo(end);
}

public void printResult() {
System.out.println(pathListMap);
}

public Map<Integer, List<Integer>> getPathListMap() {
return pathListMap;
}

public static void main(String[] args) {
/*
* int [][] graph = { { INF, 10, INF, 30, 100}, { INF, INF, 50, INF,
* INF}, { INF, INF, INF, INF, 10}, { INF, INF, 20, INF, 60}, { INF,
* INF, INF, INF, INF}};
*/
int[][] graph = { { INF, INF, 10, INF, 30, 100 },
{ INF, INF, 5, INF, INF, INF },
{ INF, INF, INF, 50, INF, INF },
{ INF, INF, INF, INF, INF, 10 },
{ INF, INF, INF, 20, INF, 60 },
{ INF, INF, INF, INF, INF, INF }, };
int start = 0;
int end = 0;
int length = graph.length;
for (start = 0; start < length; start++) {
System.out.println();
Dijkstra dijkstra = new Dijkstra(graph, start);
dijkstra.printResult();
for (end = 0; end < length; end++) {
if (end == start) {
continue;
}
int len = dijkstra.getLength(end);
System.out.println(" Length(" + start + "-" + end + ") = "
+ ((len == INF) ? "Infinity" : len));
}
}
}
}

Ⅶ 自然語言處理(NLP)的基礎難點:分詞演算法

自然語言處理(NLP,Natural Language Processing)是人工智慧領域中的一個重要方向,主要研究人與計算機之間用自然語言進行有效通信的各種理論和方法。自然語言處理的底層任務由易到難大致可以分為詞法分析、句法分析和語義分析。分詞是詞法分析(還包括詞性標注和命名實體識別)中最基本的任務,也是眾多NLP演算法中必不可少的第一步,其切分准確與否往往與整體結果息息相關。

金融領域分詞的難點

分詞既簡單又復雜。簡單是因為分詞的演算法研究已經很成熟了,大部分的演算法(如HMM分詞、CRF分詞)准確率都可以達到95%以上;復雜則是因為剩下的5%很難有突破,主要可以歸結於三點:

▲粒度,即切分時的最小單位,不同應用對粒度的要求不一樣,比如「融資融券」可以是一個詞也可以是兩個詞

▲歧義,比如「恆生」一詞,既可指恆生公司,又可指恆生指數

▲未登錄詞,即未出現在演算法使用的詞典中的詞,比如不常見的專業金融術語,以及各種上市公司的名稱

在金融領域中,分詞也具有上述三個難點,並且在未登錄詞方面的難點更為突出,這是因為金融類詞彙本來就多,再加上一些專有名詞不僅有全稱還有簡稱,這就進一步增大了難度。

在實際應用中,以上難點時常會造成分詞效果欠佳,進而影響之後的任務。尤其是在一些金融業務中,有許多需要與用戶交互的場景,某些用戶會用口語化的詞彙描述業務,如果分詞錯誤會影響用戶意圖的解析,這對分詞的准確性提出了更高的要求。因此在進行NLP上層應用開發時,需要對分詞演算法有一定的了解,從而在效果優化時有能力對分詞器進行調整。接下來,我們介紹幾種常用的分詞演算法及其應用在金融中的優劣。

幾種常見的分詞演算法

分詞演算法根據其核心思想主要分為兩種:

第一種是基於字典的分詞,先把句子按照字典切分成詞,再尋找詞的最佳組合方式,包括最大匹配分詞演算法、最短路徑分詞演算法、基於N-Gram model的分詞演算法等;

第二種是基於字的分詞,即由字構詞,先把句子分成一個個字,再將字組合成詞,尋找最優的切分策略,同時也可以轉化成序列標注問題,包括生成式模型分詞演算法、判別式模型分詞演算法、神經網路分詞演算法等。

最大匹配分詞尋找最優組合的方式是將匹配到的最長片語合在一起,主要的思路是先將詞典構造成一棵Trie樹(也稱為字典樹),Trie樹由詞的公共前綴構成節點,降低了存儲空間的同時可以提升查找效率。

最大匹配分詞將句子與Trie樹進行匹配,在匹配到根結點時由下一個字重新開始進行查找。比如正向(從左至右)匹配「他說的確實在理」,得出的結果為「他/說/的確/實在/理」。如果進行反向最大匹配,則為「他/說/的/確實/在理」。

這種方式雖然可以在O(n)時間對句子進行分詞,但是只單向匹配太過絕對,尤其是金融這種詞彙較豐富的場景,會出現例如「交易費/用」、「報價單/位」等情況,所以除非某些詞的優先順序很高,否則要盡量避免使用此演算法。

最短路徑分詞演算法首先將一句話中的所有詞匹配出來,構成詞圖(有向無環圖DAG),之後尋找從起始點到終點的最短路徑作為最佳組合方式,例:

我們認為圖中每個詞的權重都是相等的,因此每條邊的權重都為1。

在求解DAG圖的最短路徑問題時,總是要利用到一種性質:即兩點之間的最短路徑也包含了路徑上其他頂點間的最短路徑。比如S->A->B->E為S到E到最短路徑,那S->A->B一定是S到B到最短路徑,否則會存在一點C使得d(S->C->B)<d(S->A->B),那S到E的最短路徑也會變為S->C->B->E,這就與假設矛盾了。利用上述的最優子結構性質,可以利用貪心演算法或動態規劃兩種求解演算法:

(1)基於Dijkstra演算法求解最短路徑,該演算法適用於所有帶權有向圖,求解源節點到其他所有節點的最短路徑,並可以求得全局最優解;

(2)N-最短路徑分詞演算法,該方法是對Dijkstra演算法的擴展,在每一步保存最短的N條路徑,並記錄這些路徑上當前節點的前驅,在最後求得最優解時回溯得到最短路徑。這種方法的准確率優於Dijkstra演算法,但在時間和空間復雜度上都更大。

相較於最大匹配分詞演算法,最短路徑分詞演算法更加靈活,可以更好地把詞典中的片語合起來,能更好地解決有歧義的場景。比如上述「他說的確實在理」這句話,用最短路徑演算法的計算結果為「他/說/的/確實/在理」,避免了正向最大匹配的錯誤。但是對於詞典中未存在的詞基本沒有識別能力,無法解決金融領域分詞中的「未登錄詞」難點。

N-Gram(又稱N元語法模型)是基於一個假設:第n個詞出現與前n-1個詞相關,而與其他任何詞不相關。在此種假設下,可以簡化詞的條件概率,進而求解整個句子出現的概率。

現實中,常用詞的出現頻率或者概率肯定比罕見詞要大。因此,可以將求解詞圖最短路徑的問題轉化為求解最大概率路徑的問題,即分詞結果為「最有可能的詞的組合「。

計算詞出現的概率,僅有詞典是不夠的,還需要充足的語料,所以分詞任務已經從單純的「演算法」上升到了「建模」,即利用統計學方法結合大數據挖掘,對「語言」(句子出現的概率)進行建模。

我們將基於N-gram模型所統計出的概率分布應用到詞圖中,可以得到詞的概率圖。對該詞圖用最短路徑分詞演算法求解最大概率的路徑,即可得到分詞結果。

相較於前兩種分詞演算法,基於N-Gram model的分詞演算法對詞頻進行了統計建模,在切分有歧義的時候力求得到全局最優值,比如在切分方案「證券/自營/業務」和「證券/自/營業/務」中,統計出「證券/自營/業務」出現的概率更大,因此結果有更高的准確率。但也依然無法解決金融場景中未登錄詞的問題。

生成式模型主要有隱馬爾可夫模型(HMM,Hidden Markov Model)、樸素貝葉斯分類等。HMM是常用的分詞模型,基於Python的jieba分詞器和基於Java的HanLP分詞器都使用了HMM。

HMM模型認為在解決序列標注問題時存在兩種序列,一種是觀測序列,即人們顯性觀察到的句子,另一種是隱狀態序列,即觀測序列的標簽。假設觀測序列為X,隱狀態序列是Y,則因果關系為Y->X。因此要得到標注結果Y,必須對X的概率、Y的概率、P(X|Y)進行計算,即建立P(X,Y)的概率分布模型。

HMM演算法可以在一定程度上解決未登錄詞的問題,但生成式模型的准確率往往沒有接下來要談到的判別式模型高。

判別式模型主要有感知機、支持向量機(SVM,Support Vector Machine)、條件隨機場(CRF,Conditional Random Field)、最大熵模型等,其中感知機模型和CRF模型是常用的分詞模型。

(1)平均感知機分詞演算法

感知機是一種簡單的二分類線性模型,通過構造超平面,將特徵空間(輸入空間)中的樣本分為正負兩類。通過組合,感知機也可以處理多分類問題。但由於每次迭代都會更新模型的所有權重,被誤分類的樣本會造成很大影響,因此採用平均的方法,在處理完一部分樣本後對更新的權重進行平均。

(2)CRF分詞演算法

CRF可以看作一個無向圖模型,假設給定的標注序列為Y,觀測序列為X,CRF對條件概率P(Y|X)進行定義,而不是對聯合概率建模。

平均感知機演算法雖然速度快,但仍不夠准確。適合一些對速度要求高、對准確性要求相對不那麼高的場景。CRF分詞演算法可以說是目前最常用的分詞、詞性標注和實體識別演算法,它對未登陸詞也有很好的識別能力,是目前在速度、准確率以及未登錄詞識別上綜合表現最突出的演算法,也是我們目前所採用的解決方案,但速度會比感知機慢一些。

在NLP中,最常用的神經網路為循環神經網路(RNN,Recurrent Neural Network),它在處理變長輸入和序列輸入問題中有著巨大的優勢。LSTM(Long Short-Term Memory,長短期記憶網路)為RNN變種的一種,在一定程度上解決了RNN在訓練過程中梯度消失和梯度爆炸的問題。

目前對於序列標注任務,業內公認效果最好的模型是BiLSTM+CRF。相比於上述其它模型,雙向循環神經網路BiLSTM,可以更好地編碼當前字等上下文信息,並在最終增加CRF層,核心是用Viterbi演算法進行解碼,以得到全局最優解,避免B,S,E這種不可能的標記結果的出現,提高准確率。

神經網路分詞雖然能在准確率、未登錄詞識別上有更好的表現,但RNN無法並行計算,在速度上沒有優勢,所以該演算法通常在演算法研究、句子精確解析等對速度要求不高的場景下使用。

分詞作為NLP底層任務之一,既簡單又重要,很多時候上層演算法的錯誤都是由分詞結果導致的。因此,對於底層實現的演算法工程師,不僅需要深入理解分詞演算法,更需要懂得如何高效地實現和調試。

而對於上層應用的演算法工程師,在實際分詞時,需要根據業務場景有選擇地應用上述演算法,比如在搜索引擎對大規模網頁進行內容解析時,對分詞對速度要求大於精度,而在智能問答中由於句子較短,對分詞的精度要求大於速度。

Ⅷ 求java實現矩陣圖上任意兩點的最短路徑源碼

我用的是遞歸調用方法,有個小問題就是在列印步數的時候是返向的,原因是就是程序不斷的調用自己,到最後判斷基值位準退出調用。這才開始從棧里取出方法進行執行的原因。

代碼欣賞:

publicstaticintstep=1;

=newStringBuffer();

publicstaticint[][]maze={{1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,0,1,0,0,0,0,0,1},

{1,0,1,0,0,0,1,0,1,1,1},

{1,0,0,0,1,0,1,0,0,0,1},

{1,0,1,1,0,0,1,0,0,1,1},//0代表可以通過,1代表不可通過

{1,0,1,0,1,1,0,1,0,0,1},

{1,0,0,0,0,0,0,0,1,0,1},

{1,0,1,0,1,0,1,0,1,0,1},

{1,0,0,1,0,0,1,0,1,0,1},

{1,1,1,1,1,1,1,1,1,1,1}};

publicstaticvoidmain(String[]args){

inti,j;//循環記數變數

Sample.way(1,1);//二維數組起始值從下標1,1開始

System.out.println("起點從坐標x=1,y=1開始");

System.out.println("終點坐標是x=8,y=9結束");

System.out.println("這是迷宮圖表");

System.out.println("012345678910");

System.out.println("+---+---+---+---+---+---+---+---+---+---+---+---+---+");

for(i=0;i<10;i++){

System.out.print(""+i+"‖");

for(j=0;j<11;j++)

System.out.print("-"+maze[i][j]+"-‖");

System.out.println("");

System.out.println("+---+---+---+---+---+---+---+---+---+---+---+---+---+");

}

//列印顯示步數

System.out.print(printStep.toString());

}

publicstaticbooleanway(intx,inty){

if(maze[8][9]==2)//代表遞歸終止條件(也就是當走出出口時標記為2)

returntrue;

else{

if(maze[y][x]==0){

maze[y][x]=2;

/*

*下面if判斷條件代表當前坐標為基點,

*根據判斷對當前位置進行遞歸調用:如:

*往上、往右上、往右、往右下、往下、

*往左下、往左、往左上的坐標是否可走,

*判斷是否可走的返回條件是:

*2代表可通過、1代表不能通過、3表示已經走過,但是未能走通。

*/

if(way(x,y-1)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}elseif(way(x+1,y-1)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}elseif(way(x+1,y)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}elseif(way(x+1,y+1)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}elseif(way(x,y+1)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}elseif(way(x-1,y+1)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}elseif(way(x-1,y)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}elseif(way(x-1,y-1)){

printStep.append("第"+step+"步的所走的位置是x="+x+"y="+y+" ");

step++;

returntrue;

}else{

maze[y][x]=3;

returnfalse;

}

}else

returnfalse;

}

}

復制代碼前需要樓主自己創建個類

Sample.way(1,1);這句代碼是我的類的靜態調用,改下XXXXX.way(1,1);

XXXXX代表你創建的類。

下面是這個程序運行後的截圖

Ⅸ java如何實現 深度優先 廣度優先

下面是我修改了滴源碼,是基於一張簡單的地圖,在地圖上搜索目的節點,依次用深度優先、廣度優先、Dijkstra演算法實現。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Stack;

/**
*
* @author yinzhuo
*
*/
public class Arithmatic {
boolean flag = true;
// 一張地圖
static int[][] map = new int[][]// 地圖數組
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

Ⅹ 在java中,死鎖形成的原因是

死鎖是進程死鎖的簡稱,是由Dijkstra於1965年研究銀行家演算法時首先提出來的。它是計算機操作系統乃至並發程序設計中最難處理的問題之一。實際上,死鎖問題不僅在計算機系統中存在,在我們日常生活中它也廣泛存在。
1.什麼是死鎖
我們先看看這樣一個生活中的例子:在一條河上有一座橋,橋面較窄,只能容納一輛汽車通過,無法讓兩輛汽車並行。如果有兩輛汽車A和B分別由橋的兩端駛上該橋,則對於A車來說,它走過橋面左面的一段路(即佔有了橋的一部分資源),要想過橋還須等待B車讓出右邊的橋面,此時A車不能前進;對於B車來說,它走過橋面右邊的一段路(即佔有了橋的一部分資源),要想過橋還須等待A車讓出左邊的橋面,此時B車也不能前進。兩邊的車都不倒車,結果造成互相等待對方讓出橋面,但是誰也不讓路,就會無休止地等下去。這種現象就是死鎖。如果把汽車比做進程,橋面作為資源,那麽上述問題就描述為:進程A佔有資源R1,等待進程B佔有的資源Rr;進程B佔有資源Rr,等待進程A佔有的資源R1。而且資源R1和Rr只允許一個進程佔用,即:不允許兩個進程同時佔用。結果,兩個進程都不能繼續執行,若不採取其它措施,這種循環等待狀況會無限期持續下去,就發生了進程死鎖。
在計算機系統中,涉及軟體,硬體資源都可能發生死鎖。例如:系統中只有一台CD-ROM驅動器和一台列印機,某一個進程佔有了CD-ROM驅動器,又申請列印機;另一進程佔有了列印機,還申請CD-ROM。結果,兩個進程都被阻塞,永遠也不能自行解除。
所謂死鎖,是指多個進程循環等待它方佔有的資源而無限期地僵持下去的局面。很顯然,如果沒有外力的作用,那麽死鎖涉及到的各個進程都將永遠處於封鎖狀態。從上面的例子可以看出,計算機系統產生死鎖的根本原因就是資源有限且操作不當。即:一種原因是系統提供的資源太少了,遠不能滿足並發進程對資源的需求。這種競爭資源引起的死鎖是我們要討論的核心。例如:消息是一種臨時性資源。某一時刻,進程A等待進程B發來的消息,進程B等待進程C發來的消息,而進程C又等待進程A發來的消息。消息未到,A,B,C三個進程均無法向前推進,也會發生進程通信上的死鎖。另一種原因是由於進程推進順序不合適引發的死鎖。資源少也未必一定產生死鎖。就如同兩個人過獨木橋,如果兩個人都要先過,在獨木橋上僵持不肯後退,必然會應競爭資源產生死鎖;但是,如果兩個人上橋前先看一看有無對方的人在橋上,當無對方的人在橋上時自己才上橋,那麽問題就解決了。所以,如果程序設計得不合理,造成進程推進的順序不當,也會出現死鎖。
2.產生死鎖的必要條件
從以上分析可見,如果在計算機系統中同時具備下面四個必要條件時,那麽會發生死鎖。換句話說,只要下面四個條件有一個不具備,系統就不會出現死鎖。
〈1〉互斥條件。即某個資源在一段時間內只能由一個進程佔有,不能同時被兩個或兩個以上的進程佔有。這種獨占資源如CD-ROM驅動器,列印機等等,必須在佔有該資源的進程主動釋放它之後,其它進程才能佔有該資源。這是由資源本身的屬性所決定的。如獨木橋就是一種獨占資源,兩方的人不能同時過橋。
〈2〉不可搶占條件。進程所獲得的資源在未使用完畢之前,資源申請者不能強行地從資源佔有者手中奪取資源,而只能由該資源的佔有者進程自行釋放。如過獨木橋的人不能強迫對方後退,也不能非法地將對方推下橋,必須是橋上的人自己過橋後空出橋面(即主動釋放佔有資源),對方的人才能過橋。
〈3〉佔有且申請條件。進程至少已經佔有一個資源,但又申請新的資源;由於該資源已被另外進程佔有,此時該進程阻塞;但是,它在等待新資源之時,仍繼續佔用已佔有的資源。還以過獨木橋為例,甲乙兩人在橋上相遇。甲走過一段橋面(即佔有了一些資源),還需要走其餘的橋面(申請新的資源),但那部分橋面被乙佔有(乙走過一段橋面)。甲過不去,前進不能,又不後退;乙也處於同樣的狀況。
〈4〉循環等待條件。存在一個進程等待序列{P1,P2,...,Pn},其中P1等待P2所佔有的某一資源,P2等待P3所佔有的某一源,......,而Pn等待P1所佔有的的某一資源,形成一個進程循環等待環。就像前面的過獨木橋問題,甲等待乙佔有的橋面,而乙又等待甲佔有的橋面,從而彼此循環等待。
上面我們提到的這四個條件在死鎖時會同時發生。也就是說,只要有一個必要條件不滿足,則死鎖就可以排除。
8.2 死鎖的預防
前面介紹了死鎖發生時的四個必要條件,只要破壞這四個必要條件中的任意一個條件,死鎖就不會發生。這就為我們解決死鎖問題提供了可能。一般地,解決死鎖的方法分為死鎖的預防,避免,檢測與恢復三種(注意:死鎖的檢測與恢復是一個方法)。我們將在下面分別加以介紹。
死鎖的預防是保證系統不進入死鎖狀態的一種策略。它的基本思想是要求進程申請資源時遵循某種協議,從而打破產生死鎖的四個必要條件中的一個或幾個,保證系統不會進入死鎖狀態。

熱點內容
凱撒加密4 發布:2025-07-27 12:52:21 瀏覽:588
sql多條記錄合並 發布:2025-07-27 12:42:02 瀏覽:510
我的世界怎麼把材質包裝進伺服器電腦版 發布:2025-07-27 12:33:57 瀏覽:398
手游吃雞90幀要什麼配置 發布:2025-07-27 12:31:41 瀏覽:826
壓生庚演算法 發布:2025-07-27 12:31:37 瀏覽:446
伺服器版本更新是什麼意思 發布:2025-07-27 12:25:42 瀏覽:576
安卓畫畫軟體是什麼 發布:2025-07-27 12:25:40 瀏覽:644
python編程入門第3版pdf 發布:2025-07-27 12:25:04 瀏覽:873
唐燃油與h7配置哪個好 發布:2025-07-27 12:24:12 瀏覽:789
上傳圖片兼容ie8 發布:2025-07-27 12:17:45 瀏覽:552