2013-03-18 12 views
5

Dijkstraのアルゴリズムを実装する助けが必要で、誰かが私を助けてくれることを望んでいました。私はそれがいくつかのルートを印刷しているが、パスの正しいコストをキャプチャしていないようにしている。ここでDijkstraのアルゴリズムの実装が不正確な結果をもたらす

は私のノード構造である:ここで

class Node 
    { 
     public enum Color {White, Gray, Black}; 
     public string Name { get; set; } //city 
     public List<NeighborNode> Neighbors { get; set; } //Connected Edges 
     public Color nodeColor = Color.White; 
     public int timeDiscover { get; set; }//discover time 
     public int timeFinish { get; set; } // finish time 

     public Node() 
     { 
      Neighbors = new List<NeighborNode>(); 
     } 
     public Node(string n, int discover) 
     { 
      Neighbors = new List<NeighborNode>(); 
      this.Name = n; 
      timeDiscover = discover; 
     } 


     public Node(string n, NeighborNode e, decimal m) 
     { 
      Neighbors = new List<NeighborNode>(); 
      this.Name = n; 
      this.Neighbors.Add(e); 
     } 

    } 

    class NeighborNode 
    { 
     public Node Name { get; set; } 
     public decimal Miles { get; set; } //Track the miles on the neighbor node 

     public NeighborNode() { } 
     public NeighborNode(Node n, decimal m) 
     { 
      Name = n; 
      Miles = m; 
     } 

    } 

は私のアルゴリズムです:

public void DijkstraAlgorithm(List<Node> graph) 
    { 

     List<DA> _algorithmList = new List<DA>(); //track the node cost/positioning 
     Stack<Node> _allCities = new Stack<Node>(); // add all cities into this for examination 
     Node _nodeToExamine = new Node(); //this is the node we're currently looking at. 
     decimal _cost = 0; 

     foreach (var city in graph) // putting these onto a stack for easy manipulation. Probably could have just made this a stack to start 
     { 
      _allCities.Push(city); 
      _algorithmList.Add(new DA(city)); 
     } 

     _nodeToExamine = _allCities.Pop(); //pop off the first node 

     while (_allCities.Count != 0) // loop through each city 
     { 

      foreach (var neighbor in _nodeToExamine.Neighbors) //loop through each neighbor of the node 
      { 
       for (int i = 0; i < _algorithmList.Count; i++) //search the alorithm list for the current neighbor node 
       { 
        if (_algorithmList[i].Name.Name == neighbor.Name.Name) //found it 
        { 
         for (int j = 0; j < _algorithmList.Count; j++) //check for the cost of the parent node 
         { 
          if (_algorithmList[j].Name.Name == _nodeToExamine.Name) //looping through 
          { 
           if (_algorithmList[j].Cost != 100000000) //not infinity 
            _cost = _algorithmList[j].Cost; //set the cost to be the parent cost 

           break; 
          } 
         } 
         _cost = _cost + neighbor.Miles; 

         if (_algorithmList[i].Cost > _cost) // check to make sure the miles are less (better path) 
         { 
          _algorithmList[i].Parent = _nodeToExamine; //set the parent to be the top node 
          _algorithmList[i].Cost = _cost; // set the weight to be correct 
          break; 
         } 
        } 
       } 

      } 
      _cost = 0; 
      _nodeToExamine = _allCities.Pop(); 
     } 
    } 

これは以下のようにグラフが見えるものです:グラフのリストノードは、本質的に

ある enter image description here

ノード - 隣接ノード

例えばので

ノード=オリンピア、近隣ノード=レイシーとタコマ

+2

インデントの量を削減するだけで先端を、あなたは 'if'sを反転してジャンプする' continue'を使用することができます次の 'i 'に、例えば。 'if(_algorithmList [i] .Name.Name!= neighbor.Name.Name)continue;' –

答えて

0

私はそれが正しく処理されなかったとして、アルゴリズム全体を書き換える必要:

public void DijkstraAlgorithm(List<Node> graph) 
    { 

     List<DA> _algorithmList = new List<DA>(); //track the node cost/positioning 
     DA _nodeToExamine = new DA(); //this is the node we're currently looking at. 
     bool flag = true; //for exting the while loop later 

     foreach (var node in graph) 
     { 
      _algorithmList.Add(new DA(node)); 
     } 

     foreach (var children in _algorithmList[0].Name.Neighbors) //just starting at the first node 
     { 
      for (int i = 0; i < _algorithmList.Count; i++) 
      { 
       if (children.Name == _algorithmList[i].Name) 
       { 
        _algorithmList[i].Parent = _algorithmList[0].Name; 
        _algorithmList[i].Cost = children.Miles; 
        _algorithmList[0].Complete = true; 

       } 
      } 
     } 

     while (flag) //loop through the rest to organize 
     { 
      _algorithmList = _algorithmList.OrderBy(x => x.Cost).ToList(); //sort by shortest path 

      for (int i = 0; i < _algorithmList.Count; i++) //loop through each looking for a node that isn't complete 
      { 
       if (_algorithmList[i].Complete == false) 
       { 
        _nodeToExamine = _algorithmList[i]; 
        break; 
       } 
       if (i == 13) //if the counter reaches 13 then we have completed all nodes and should bail out of the loop 
        flag = false; 
      } 
      if (_nodeToExamine.Name.Neighbors.Count == 0) //set any nodes that do not have children to be complete 
      { 
       _nodeToExamine.Complete = true; 
      } 

      foreach (var children in _nodeToExamine.Name.Neighbors) //loop through the children/neighbors to see if there's one with a shorter path 
      { 
       for (int i = 0; i < _algorithmList.Count; i++) 
       { 
        if (children.Name == _algorithmList[i].Name) 
        { 
         if (_nodeToExamine.Cost + children.Miles < _algorithmList[i].Cost) //found a better path 
         { 
          _algorithmList[i].Parent = _nodeToExamine.Name; 
          _algorithmList[i].Cost = _nodeToExamine.Cost + children.Miles; 
         } 
        } 
       } 
       _nodeToExamine.Complete = true; 
      } 
     } 

     PrintDijkstraAlgoirthm(_algorithmList); 
    } 


    public void PrintDijkstraAlgoirthm(List<DA> _finalList) 
    { 
     foreach (var item in _finalList) 
     { 
      if (item.Parent != null) 
       Console.WriteLine("{0} ---> {1}: {2}", item.Parent.Name, item.Name.Name, item.Cost); 
     } 
    } 
4

は、私はこの問題は、それが

_cost = _algorithmList[j].Cost; //set the cost to be the parent costだと思います

あなたはco古いと新しいコストの追加の代わりに、st。また

、それはパスのコストが無限大である場合は、あなたは非常に反対のやることを意味する前に、あなたが

if (_algorithmList[j].Cost != 100000000) //not infinity

直接やるということ - あなたはコストをゼロを追加最も高価なパスではなく、最も安価なパスになります。

無限大を正しく確認したい場合は、コスト計算をスキップするだけでなく、コストを検査するときにそのパスをスキップする必要があります。

+0

私は完全にフォローしていません。最初の参照(_コスト割り当て) - 私は隣のノードのコストを下の親ノードのコストに加えます。この背後にある私の思考プロセスは、コストがどうあるべきかということです。親ノード+現在のノード...理論的には、親ノードには総コストがあります。 2番目のリファレンスでは、ノードが既に見られているかどうかを確認することです(別名親が見つかった)。申し訳ありませんが、コードを改善して動作させる方法はまったくありません。どうか明らかにしてください!ありがとう:) – Yecats

+0

@Yecatsあなたのアルゴリズムは、より微妙な方法で間違っている必要があります...私は再びそれを櫛を介して待機してください平均時間で、おそらくデバッガ/貧しい人のデバッガを使用し、疑い深く間違っている?わずか3〜4辺のような非常に簡単なグラフでテストすることもできます – Patashu

関連する問題