dijkstra演算法java
1. 求大佬用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")
2. 迪傑斯特拉演算法問題,求pascal代碼詳解,有重賞!
packageminRoad.no;importjava.util.Arrays;//這個程序用來求得一個圖的最短路徑矩陣publicclassShortestDistance_V4{privatestaticfinalintinf=Integer.MAX_VALUE;//表示兩個點之間無法直接連通publicstaticint[][]dijkstra(int[][]graph){intmin,v,u=0,n=graph.length;int[]path=newint[n];int[]dist=newint[n];boolean[]s=newboolean[n];Arrays.fill(s,false);Arrays.fill(dist,inf);for(inti=0;i******A--------30------->D*|\∧|*|\/|*|\/|*|1010|*|\/20*|\/|*|\/|*|∨/∨*20BE*|/∧*|//*|//*|5/*|/30*|//*|//*∨∠/*C***@paramargs*/publicstaticvoidmain(String[]args){int[][]W1={{0,10,20,30,inf},{10,0,5,10,inf},{20,5,0,inf,30},{30,10,inf,0,20},{inf,inf,30,20,0},};///2799422/1163565//int[][]W={//{0,1,4,inf,inf,inf},//{1,0,2,7,5,inf},//{4,2,0,inf,1,inf},//{inf,7,inf,0,3,2},//{inf,5,1,3,0,6},//{inf,inf,inf,2,6,0}};int[][]distAndShort=dijkstra(W1);System.out.println(Arrays.toString(distAndShort[0]));System.out.println(Arrays.toString(distAndShort[1]));//distance:{0,1,3,7,4,9};}}
3. 矩陣怎麼用來計算dijkstra演算法 java
怎樣用matlab編程實現Dijkstra演算法
%單源點最短路徑Dijkstra演算法實現
function [d index1 index2] = Dijkf(a)
% a 表示圖的權值矩陣
% d 表示所求最短路的權和
% index1 表示標號頂點順序
% index2 表示標號頂點索引
%參數初始化
M= max(max(a));
pb(1:length(a))= 0; % 標記向量,表明是否已進入S集合
pb(1)= 1;
index1= 1;
index2= ones(1,length(a));
d(1:length(a))= M; % d矩陣所有元素都初始化為最大權值
d(1)= 0; % 以v1點為源點
temp= 1;
% 更新l(v),同時記錄頂點順序和頂點索引
while sum(pb)<length(a) % 重復步驟2,直到滿足停止條件
tb= find(pb==0);
d(tb)= min(d(tb),d(temp)+a(temp,tb)); % 更新l(v)
tmpb= find(d(tb)==min(d(tb))); % 找出min(l(v))
temp= tb(tmpb(1));
pb(temp)= 1;
index1= [index1,temp]; % 記錄標號順序
index= index1(find(d(index1)==d(temp)-a(temp,index1)));
if length(index)>=2
index= index(1);
end % if結束
index2(temp)= index; % 記錄標號索引
end % while結束
end
% Dijkf函數結束
4. Dijkstra演算法在城市交通中的應用
剛開始的話,建議你先不要考慮如何應用,先學習一下演算法,弄明白演算法原理之後再考慮如何進行實際應用。
如果演算法已經搞懂了(起碼要能夠自己編程實現演算法,並自己設計測試數據進行測試),就可以考慮應用了。
這里先簡單說說,首先要有數據(巧演算法難為無數據之運算^_^),這里你需要有一些節點,以及節點之間的距離。所以,無論你是用現成的地圖還是自己畫,都需要從圖上選取一些點,記錄這些點的位置和該點到其他點的直接距離(也就是不通過第三點的距離,比如一條路上順次有abc三個點,ac之間的距離就不計在內了,因為需要通過b點),然後。。。。也就沒什麼然後了,直接算就是了^_^
再說說節點選取,一般來講,地圖上的節點通常有一下幾類:公交站、知名建築、地標、橋梁等,由於你是做畢設,因此隨便選一些能夠表現出效果就好了(況且太多點運算量大,容易死機的說^_^)
還有,如何表現出其應用價值呢?做個界面吧,應用程序(推薦Java/Delphi/VB)或者網頁(推薦JSP/PHP/ASP等)都行,界面上起碼要有個「查詢從A到B的最短路徑」功能,然後,當然還要顯示查詢結果啦,如果你有興致,可以搞個圖片,然後在她們所要經過的最短路徑上畫線(只要能連接路線途經的節點就夠了),這樣就可以直觀的看出該路線在地圖上究竟如何。到這里,基本上也就差不多了,不信你去看看那網路地圖的這個功能,也就那麼回事兒^_^
最後,作為畢設嘛,重點不全在應用,還應有對該技術的優勢、劣勢、改進方法等等的分析,這一點就需要更多閱讀啦,如果真的有意做好它,不如等做到這一步再來探討吧^_^
加油!祝你好運^_^
5. 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 } };
6. 尋求大神幫忙寫Java代碼,要用Dijkstra』s algorithm(迪傑斯特拉演算法)
package minRoad.no;
import java.util.Arrays;
//這個程序用來求得一個圖的最短路徑矩陣
public class ShortestDistance_V4 {
private static final int inf = Integer.MAX_VALUE;// 表示兩個點之間無法直接連通
public static int[][] dijkstra(int[][] graph) {
int min, v, u = 0, n = graph.length;
int[] path = new int[n];
int[] dist = new int[n];
boolean[] s = new boolean[n];
Arrays.fill(s, false);
Arrays.fill(dist, inf);
for (int i = 0; i < n; i++) {
dist[i] = graph[u][i];
if (i != u && dist[i] < inf)
path[i] = u;
else
path[i] = -1;
}
s[u] = true;
while (true) {
min = inf;
v = -1;
// 找到最小的dist
for (int i = 0; i < n; i++) {
if (!s[i]) {
if (dist[i] < min) {
min = dist[i];
v = i;
}
}
}
if (v == -1) break;// 找不到更短的路徑了
// 更新最短路徑
s[v] = true;
for (int i = 0; i < n; i++) {
if (!s[i] && graph[v][i] != inf && dist[v] + graph[v][i] < dist[i]) {
dist[i] = dist[v] + graph[v][i];
path[i] = v;
}
}
}
// 輸出路徑
int[] shortest = new int[n];
for (int i = 1; i < n; i++) {
Arrays.fill(shortest, 0);
int k = 0;
shortest[k] = i;
while (path[shortest[k]] != 0) {
k++;
shortest[k] = path[shortest[k - 1]];
}
k++;
shortest[k] = 0;
}
int[] tmp = new int[shortest.length];
for (int i = 0; i < tmp.length; i++) {
tmp[i] = shortest[tmp.length - i - 1];
}
return new int[][] { dist, tmp };
}
/**
* <pre>
* v0
* 1, v1
* 4, 2, v2
* inf, 7, -1, v3
* inf, 5, 1, 3, v4
* inf, inf, inf, 2, 6, v5
* </pre>
*
* *
*
* <pre>
* A--------30------->D
* |\ ∧|
* | \ / |
* | \ / |
* | 10 10 |
* | \ / 20
* | \ / |
* | \ / |
* | ∨ / ∨
* 20 B E
* | / ∧
* | / /
* | / /
* | 5 /
* | / 30
* | / /
* | / /
* ∨∠ /
* C
* </pre>
*
* @param args
*/
public static void main(String[] args) {
int[][] W1 = {
{ 0, 10, 20, 30, inf },
{ 10, 0, 5, 10, inf },
{ 20, 5, 0, inf, 30 },
{ 30, 10, inf, 0, 20 },
{ inf, inf, 30, 20, 0 },
};
// http://sbp810050504.blog.51cto.com/2799422/690803
// http://sbp810050504.blog.51cto.com/2799422/1163565
// int[][] W = {
// { 0, 1, 4, inf, inf, inf },
// { 1, 0, 2, 7, 5, inf },
// { 4, 2, 0, inf, 1, inf },
// { inf, 7, inf, 0, 3, 2 },
// { inf, 5, 1, 3, 0, 6 },
// { inf, inf, inf, 2, 6, 0 }};
int[][] distAndShort = dijkstra(W1);
System.out.println(Arrays.toString(distAndShort[0]));
System.out.println(Arrays.toString(distAndShort[1]));
// distance: { 0, 1, 3, 7, 4, 9};
}
}
7. 用java怎麼用迪傑斯特拉算有向圖有權值的最短路徑
Dijkstra(迪傑斯特拉)演算法是典型的最短路徑路由演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴展,直到擴展到終點為止。
Dijkstra一般的表述通常有兩種方式,一種用永久和臨時標號方式,一種是用OPEN, CLOSE表方式
用OPEN,CLOSE表的方式,其採用的是貪心法的演算法策略,大概過程如下:
1.聲明兩個集合,open和close,open用於存儲未遍歷的節點,close用來存儲已遍歷的節點
2.初始階段,將初始節點放入close,其他所有節點放入open
3.以初始節點為中心向外一層層遍歷,獲取離指定節點最近的子節點放入close並從新計算路徑,直至close包含所有子節點
代碼實例如下:
Node對象用於封裝節點信息,包括名字和子節點
[java] view plain
public class Node {
private String name;
private Map<Node,Integer> child=new HashMap<Node,Integer>();
public Node(String name){
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<Node, Integer> getChild() {
return child;
}
public void setChild(Map<Node, Integer> child) {
this.child = child;
}
}
MapBuilder用於初始化數據源,返回圖的起始節點
[java] view plain
public class MapBuilder {
public Node build(Set<Node> open, Set<Node> close){
Node nodeA=new Node("A");
Node nodeB=new Node("B");
Node nodeC=new Node("C");
Node nodeD=new Node("D");
Node nodeE=new Node("E");
Node nodeF=new Node("F");
Node nodeG=new Node("G");
Node nodeH=new Node("H");
nodeA.getChild().put(nodeB, 1);
nodeA.getChild().put(nodeC, 1);
nodeA.getChild().put(nodeD, 4);
nodeA.getChild().put(nodeG, 5);
nodeA.getChild().put(nodeF, 2);
nodeB.getChild().put(nodeA, 1);
nodeB.getChild().put(nodeF, 2);
nodeB.getChild().put(nodeH, 4);
nodeC.getChild().put(nodeA, 1);
nodeC.getChild().put(nodeG, 3);
nodeD.getChild().put(nodeA, 4);
nodeD.getChild().put(nodeE, 1);
nodeE.getChild().put(nodeD, 1);
nodeE.getChild().put(nodeF, 1);
nodeF.getChild().put(nodeE, 1);
nodeF.getChild().put(nodeB, 2);
nodeF.getChild().put(nodeA, 2);
nodeG.getChild().put(nodeC, 3);
nodeG.getChild().put(nodeA, 5);
nodeG.getChild().put(nodeH, 1);
nodeH.getChild().put(nodeB, 4);
nodeH.getChild().put(nodeG, 1);
open.add(nodeB);
open.add(nodeC);
open.add(nodeD);
open.add(nodeE);
open.add(nodeF);
open.add(nodeG);
open.add(nodeH);
close.add(nodeA);
return nodeA;
}
}
圖的結構如下圖所示:
Dijkstra對象用於計算起始節點到所有其他節點的最短路徑
[java] view plain
public class Dijkstra {
Set<Node> open=new HashSet<Node>();
Set<Node> close=new HashSet<Node>();
Map<String,Integer> path=new HashMap<String,Integer>();//封裝路徑距離
Map<String,String> pathInfo=new HashMap<String,String>();//封裝路徑信息
public Node init(){
//初始路徑,因沒有A->E這條路徑,所以path(E)設置為Integer.MAX_VALUE
path.put("B", 1);
pathInfo.put("B", "A->B");
path.put("C", 1);
pathInfo.put("C", "A->C");
path.put("D", 4);
pathInfo.put("D", "A->D");
path.put("E", Integer.MAX_VALUE);
pathInfo.put("E", "A");
path.put("F", 2);
pathInfo.put("F", "A->F");
path.put("G", 5);
pathInfo.put("G", "A->G");
path.put("H", Integer.MAX_VALUE);
pathInfo.put("H", "A");
//將初始節點放入close,其他節點放入open
Node start=new MapBuilder().build(open,close);
return start;
}
public void computePath(Node start){
Node nearest=getShortestPath(start);//取距離start節點最近的子節點,放入close
if(nearest==null){
return;
}
close.add(nearest);
open.remove(nearest);
Map<Node,Integer> childs=nearest.getChild();
for(Node child:childs.keySet()){
if(open.contains(child)){//如果子節點在open中
Integer newCompute=path.get(nearest.getName())+childs.get(child);
if(path.get(child.getName())>newCompute){//之前設置的距離大於新計算出來的距離
path.put(child.getName(), newCompute);
pathInfo.put(child.getName(), pathInfo.get(nearest.getName())+"->"+child.getName());
}
}
}
computePath(start);//重復執行自己,確保所有子節點被遍歷
computePath(nearest);//向外一層層遞歸,直至所有頂點被遍歷
}
public void printPathInfo(){
Set<Map.Entry<String, String>> pathInfos=pathInfo.entrySet();
for(Map.Entry<String, String> pathInfo:pathInfos){
System.out.println(pathInfo.getKey()+":"+pathInfo.getValue());
}
}
/**
* 獲取與node最近的子節點
*/
private Node getShortestPath(Node node){
Node res=null;
int minDis=Integer.MAX_VALUE;
Map<Node,Integer> childs=node.getChild();
for(Node child:childs.keySet()){
if(open.contains(child)){
int distance=childs.get(child);
if(distance<minDis){
minDis=distance;
res=child;
}
}
}
return res;
}
}
Main用於測試Dijkstra對象
[java] view plain
public class Main {
public static void main(String[] args) {
Dijkstra test=new Dijkstra();
Node start=test.init();
test.computePath(start);
test.printPathInfo();
}
}
8. 求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代表你創建的類。
下面是這個程序運行後的截圖
9. 在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 死鎖的預防
前面介紹了死鎖發生時的四個必要條件,只要破壞這四個必要條件中的任意一個條件,死鎖就不會發生。這就為我們解決死鎖問題提供了可能。一般地,解決死鎖的方法分為死鎖的預防,避免,檢測與恢復三種(注意:死鎖的檢測與恢復是一個方法)。我們將在下面分別加以介紹。
死鎖的預防是保證系統不進入死鎖狀態的一種策略。它的基本思想是要求進程申請資源時遵循某種協議,從而打破產生死鎖的四個必要條件中的一個或幾個,保證系統不會進入死鎖狀態。
10. dijkstra的優化可以用數組+優先隊列嗎
基於java類庫的PriorityQueue的PriorityQueue+Dijkstra實現:
[java]view plain
importjava.util.HashMap;
importjava.util.HashSet;
importjava.util.Iterator;
importjava.util.PriorityQueue;
importjava.util.Scanner;
importjava.util.Set;
/**
*PriorityQueue+Dijkstra演算法求單源最短路徑
*首推此方法
*雖然優先順序隊列優化比堆優化性能差一點,差距很小。
*但是優先順序隊列可以直接使用java類庫中的PriorityQueue來實現,
*而堆優化實現非常復雜。
*
*@authorDuXiangYu
*
*/
publicclassDijKstra_link_Queue{
staticintnodeCount;
staticintedgeCount;
//鄰接表表頭數組
staticNode[]firstArray;
//最短路徑數組
//staticint[]dist;
//S集合,代表著已經找到最短路徑的結點
staticHashSet<Integer>s;
//映射集合
staticdist[]distArray;
//優先順序隊列
staticPriorityQueue<dist>pq;
staticintmax=1000000;
/**
*結點類
*
*@authorDuXiangYu
*/
staticclassNode{
//鄰接頂點map
privateHashMap<Integer,Integer>map=null;
publicvoidaddEdge(intend,intedge){
if(this.map==null){
this.map=newHashMap<Integer,Integer>();
}
this.map.put(end,edge);
}
}
/**
*dist:保存源結點至每個結點的最短路徑
*@authorDuXiangYu
*
*/
<dist>{
intvalue;
intindex;
publicdist(intvalue,intindex){
this.value=value;
this.index=index;
}
@Override
publicintcompareTo(disto){
if(o.value<this.value){
return1;
}elseif(o.value>this.value){
return-1;
}else{
return0;
}
}
}
publicstaticvoidmain(String[]args){
Scannersc=newScanner(System.in);
nodeCount=sc.nextInt();
edgeCount=sc.nextInt();
firstArray=newNode[nodeCount+1];
for(inti=0;i<nodeCount+1;i++){
firstArray[i]=newNode();
}
for(inti=0;i<edgeCount;i++){
intbegin=sc.nextInt();
intend=sc.nextInt();
intedge=sc.nextInt();
firstArray[begin].addEdge(end,edge);
}
sc.close();
longbegin=System.currentTimeMillis();
djst();
longend=System.currentTimeMillis();
System.out.println(end-begin+"ms");
}
/**
*PriorityQueue+Dijkstra演算法實現
*/
privatestaticvoiddjst(){
s=newHashSet<Integer>();
pq=newPriorityQueue<dist>(nodeCount);
distArray=newdist[nodeCount+1];
NodetempNode=firstArray[1];
for(inti=2;i<nodeCount+1;i++){
HashMap<Integer,Integer>tempMap=tempNode.map;
if(tempMap.containsKey(i)){
distd=newdist(tempMap.get(i),i);
pq.offer(d);
distArray[i]=d;
}else{
distd=newdist(max,i);
pq.offer(d);
distArray[i]=d;
}
}
s.add(1);
while(s.size()<nodeCount){
distd=pq.poll();
intindex=d.index;
intvalue=d.value;
s.add(index);
//用indx這個點去更新它的鄰接點到開始點的距離
HashMap<Integer,Integer>m=firstArray[index].map;
if(m==null){
continue;
}
Set<Integer>set=m.keySet();
Iterator<Integer>it=set.iterator();
while(it.hasNext()){
intnum=it.next();
if(num==1){
continue;
}
disttempDist=distArray[num];
if(m.get(num)+value<tempDist.value){
pq.remove(tempDist);
tempDist.value=m.get(num)+value;
pq.offer(tempDist);
distArray[num]=tempDist;
}
}
}
for(inti=2;i<nodeCount+1;i++){
System.out.println(distArray[i].value);
}
}
}</span></span>