Out of Memory错误在实现广度优先搜索算法时发生。

huangapple go评论75阅读模式
英文:

Out of Memory error when implementing breadth first search algorithm

问题

以下是您的代码的翻译部分:

我遇到了以下错误:

```text
[error][1] (E/DartVM  (14988): 耗尽堆空间,尝试分配 536870928 字节。
E/flutter (14988): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] 未处理的异常:内存不足)

当尝试实现广度优先搜索算法以找到图中的最短路径时,我找到了C#中的算法,现在正尝试将其重写为Dart/Flutter。

原始的C#代码在这里

我的Dart代码:

import 'dart:collection';
import 'package:stack/stack.dart';

class Node<T> {
  int id;
  Node(this.id);
  String toString() => '$id';
}

class Graph<T> {
  final Map<Node, List<Node>> adj;
  Graph(this.adj);
  void AddEdge(Node node1, Node node2) {
    if (!adj.containsKey(node1))
      adj[node1] = List<Node>();
    if (!adj.containsKey(node2))
      adj[node2] = List<Node>();
    adj[node1].add(node2);
    adj[node2].add(node1);
  }

  Stack<Node> ShortestPath(Node source, Node dest) {
    var path = Map<Node<T>, Node<T>>();
    var distance = Map<Node<T>, int>();
    for (var node in adj.keys) {
      distance[node] = -1;
    }
    distance[source] = 0;
    var q = Queue<Node<T>>();
    q.add(source);
    while (q.isNotEmpty) {
      var node = q.removeFirst();
      for (var adjs in adj[node].where((n) => distance[n] == -1)) {
        distance[adjs] = distance[node] + 1;
        path[adjs] = node;
        q.add(adjs);
      }
    }
    var res = Stack<Node>();
    var cur = dest;
    while (cur != res) {
      res.push(cur);
      cur = path[cur];
    }
    res.push(source);
    return res;
  }
}

void main() {
  var g = new Graph({});
  var n1 = new Node<int>(1);
  var n2 = new Node<int>(2);
  var n3 = new Node<int>(3);
  var n4 = new Node<int>(4);
  var n5 = new Node<int>(5);
  var n6 = new Node<int>(6);
  var n7 = new Node<int>(7);
  g.AddEdge(n1, n2);
  g.AddEdge(n1, n3);
  g.AddEdge(n1, n4);
  g.AddEdge(n4, n5);
  g.AddEdge(n2, n6);
  g.AddEdge(n4, n7);
  g.AddEdge(n5, n6);
  g.AddEdge(n6, n7);
  var answ = g.ShortestPath(n1, n7);
  print(answ);
}

这是您的代码的中文翻译,不包含问题的答案。如果您有其他问题或需要进一步帮助,请随时提出。

英文:

I got the following error:

[error][1] (E/DartVM  (14988): Exhausted heap space, trying to allocate 536870928 bytes.
E/flutter (14988): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Out of Memory)

When trying to implement a breadth_first search algorithm to find the shortest path in a graph. I found the algorithm written in C# and I am trying to rewrite it in dart/flutter.

The original code in C# can be found here.

My dart code:

import &#39;dart:collection&#39;;
import &#39;package:stack/stack.dart&#39;;
class Node&lt;T&gt;{
  int id;
  Node(this.id);
  String toString() =&gt; &#39;$id&#39;;
}
class Graph&lt;T&gt;{
  final Map&lt;Node, List&lt;Node&gt;&gt; adj;
  Graph(this.adj);
  void AddEdge(Node node1,Node node2){
    if(!adj.containsKey(node1))
      adj[node1]=List&lt;Node&gt;();
    if(!adj.containsKey(node2))
      adj[node2]=List&lt;Node&gt;();
    adj[node1].add(node2);
    adj[node2].add(node1);
  }
  Stack&lt;Node&gt; ShortestPath(Node source, Node dest){
    var path=Map&lt;Node&lt;T&gt;,Node&lt;T&gt;&gt;();
    var distance=Map&lt;Node&lt;T&gt;,int&gt;();
    //adj.keys.forEach(( node) =&gt; distance[node]=-1);
    for(var node in adj.keys){
      distance[node]=-1;
    }
    distance[source]=0;
    var q=Queue&lt;Node&lt;T&gt;&gt;();
    q.add(source);
    while(q.isNotEmpty){
      var node=q.removeFirst();
      for(var adjs in adj[node].where((n) =&gt; distance[n]==-1)){
        distance[adjs]=distance[node]+1;
        path[adjs]=node;
        q.add(adjs);
      }
    }
    var res=Stack&lt;Node&gt;();
    var cur=dest;
    while(cur != res){
      res.push(cur);
      cur=path[cur];
    }
    res.push(source);
    return res;
  }
}
void main() {
  var g = new Graph({});
  var n1 = new Node&lt;int&gt;(1);
  var n2 = new Node&lt;int&gt;(2);
  var n3 = new Node&lt;int&gt;(3);
  var n4 = new Node&lt;int&gt;(4);
  var n5 = new Node&lt;int&gt;(5);
  var n6 = new Node&lt;int&gt;(6);
  var n7 = new Node&lt;int&gt;(7);
  g.AddEdge(n1, n2);
  g.AddEdge(n1, n3);
  g.AddEdge(n1, n4);
  g.AddEdge(n4, n5);
  g.AddEdge(n2, n6);
  g.AddEdge(n4, n7);
  g.AddEdge(n5, n6);
  g.AddEdge(n6, n7);
  var answ=g.ShortestPath(n1, n7);
  print(answ);
}

So what is the wrong with my program, and if anyone know better way to find shortest path in graph to use it in dart it will be great.

Thanks in advance

答案1

得分: 0

首先,您的主要问题可能是您的 while 循环与 C# 实现不正确:

var res = Stack<Node>();
var cur = dest;
while (cur != res) {
  res.push(cur);
  cur = path[cur];
}
res.push(source);
return res;

此循环永远不会结束,因为curres是完全不同的类型,其中cur是一个Node,而res是一个Stack。如果您查看 C# 实现,您会发现这是不正确的:

var res = new Stack<Node<T>>();
var cur = dest;
while (cur != source) {
  res.Push(cur);
  cur = path[cur];
}
res.Push(source);
return res;

因此,我认为通过与source进行比较,将正确解决该问题。但是您的代码中还存在许多较小的问题,其中类型不太合适,并且可以在更多地方使用泛型来增加类型安全性。

因此,我已经向您的代码添加了更多的类型信息(这是为了捕捉类型错误)。我还放弃了Stack类的使用,因为我认为这没有太多意义。此外,您获取的Stack类没有toString实现,因此我认为直接使用 List 并将其作为结果返回更容易:

import 'dart:collection';

class Node<T> {
  int id;
  Node(this.id);

  @override
  String toString() => '$id';
}

class Graph<T> {
  final Map<Node<T>, List<Node<T>>> adj;
  Graph(this.adj);
  void AddEdge(Node<T> node1, Node<T> node2) {
    if (!adj.containsKey(node1)) adj[node1] = <Node<T>>[];
    if (!adj.containsKey(node2)) adj[node2] = <Node<T>>[];
    adj[node1].add(node2);
    adj[node2].add(node1);
  }

  List<Node<T>> ShortestPath(Node<T> source, Node<T> dest) {
    final path = <Node<T>, Node<T>>{};
    final distance = <Node<T>, int>{};
    // adj.keys.forEach((node) => distance[node]=-1);
    for (final node in adj.keys) {
      distance[node] = -1;
    }
    distance[source] = 0;
    final q = Queue<Node<T>>();
    q.add(source);
    while (q.isNotEmpty) {
      final node = q.removeFirst();
      for (final adjs in adj[node].where((n) => distance[n] == -1)) {
        distance[adjs] = distance[node] + 1;
        path[adjs] = node;
        q.add(adjs);
      }
    }
    final res = <Node<T>>[];
    var cur = dest;
    while (cur != source) {
      res.add(cur);
      cur = path[cur];
    }
    res.add(source);
    return res;
  }
}

void main() {
  final g = Graph<int>({});
  final n1 = Node<int>(1);
  final n2 = Node<int>(2);
  final n3 = Node<int>(3);
  final n4 = Node<int>(4);
  final n5 = Node<int>(5);
  final n6 = Node<int>(6);
  final n7 = Node<int>(7);
  g.AddEdge(n1, n2);
  g.AddEdge(n1, n3);
  g.AddEdge(n1, n4);
  g.AddEdge(n4, n5);
  g.AddEdge(n2, n6);
  g.AddEdge(n4, n7);
  g.AddEdge(n5, n6);
  g.AddEdge(n6, n7);
  final answ = g.ShortestPath(n1, n7);
  print(answ); // [7, 4, 1]
}
英文:

First, you main problem is properly that your while loop is not correct according to the C# implementation:

    var res=Stack&lt;Node&gt;();
var cur=dest;
while(cur != res){
res.push(cur);
cur=path[cur];
}
res.push(source);
return res;

This loop will never finish res and cur are entirely different types where cur are a Node and res are a Stack. If you check the C# implementation you can see this is not correct:

		var res = new Stack&lt;Node&lt;T&gt;&gt;();
		var cur = dest;
		while(cur != source) {
			res.Push(cur);
			cur = path[cur];
		}
		res.Push(source);
		return res;

So I think by comparing against source it will properly solve the problem. But there are a lot of smaller problems in you code where types are not really great and where you could make it a lot more type safe by using generics more places.

I have therefore added more typing information to you code (which I needed to do to catch the type error). I have also dropped the usage of the Stack class since I don't think it makes much sense. Also, the Stack class you got had no toString implementation so I just thought it was easier to just use a List and return that as the result:

import &#39;dart:collection&#39;;

class Node&lt;T&gt; {
  int id;
  Node(this.id);

  @override
  String toString() =&gt; &#39;$id&#39;;
}

class Graph&lt;T&gt; {
  final Map&lt;Node&lt;T&gt;, List&lt;Node&lt;T&gt;&gt;&gt; adj;
  Graph(this.adj);
  void AddEdge(Node&lt;T&gt; node1, Node&lt;T&gt; node2) {
    if (!adj.containsKey(node1)) adj[node1] = &lt;Node&lt;T&gt;&gt;[];
    if (!adj.containsKey(node2)) adj[node2] = &lt;Node&lt;T&gt;&gt;[];
    adj[node1].add(node2);
    adj[node2].add(node1);
  }

  List&lt;Node&lt;T&gt;&gt; ShortestPath(Node&lt;T&gt; source, Node&lt;T&gt; dest) {
    final path = &lt;Node&lt;T&gt;, Node&lt;T&gt;&gt;{};
    final distance = &lt;Node&lt;T&gt;, int&gt;{};
    //adj.keys.forEach(( node) =&gt; distance[node]=-1);
    for (final node in adj.keys) {
      distance[node] = -1;
    }
    distance[source] = 0;
    final q = Queue&lt;Node&lt;T&gt;&gt;();
    q.add(source);
    while (q.isNotEmpty) {
      final node = q.removeFirst();
      for (final adjs in adj[node].where((n) =&gt; distance[n] == -1)) {
        distance[adjs] = distance[node] + 1;
        path[adjs] = node;
        q.add(adjs);
      }
    }
    final res = &lt;Node&lt;T&gt;&gt;[];
    var cur = dest;
    while (cur != source) {
      res.add(cur);
      cur = path[cur];
    }
    res.add(source);
    return res;
  }
}

void main() {
  final g = Graph&lt;int&gt;({});
  final n1 = Node&lt;int&gt;(1);
  final n2 = Node&lt;int&gt;(2);
  final n3 = Node&lt;int&gt;(3);
  final n4 = Node&lt;int&gt;(4);
  final n5 = Node&lt;int&gt;(5);
  final n6 = Node&lt;int&gt;(6);
  final n7 = Node&lt;int&gt;(7);
  g.AddEdge(n1, n2);
  g.AddEdge(n1, n3);
  g.AddEdge(n1, n4);
  g.AddEdge(n4, n5);
  g.AddEdge(n2, n6);
  g.AddEdge(n4, n7);
  g.AddEdge(n5, n6);
  g.AddEdge(n6, n7);
  final answ = g.ShortestPath(n1, n7);
  print(answ); // [7, 4, 1]
}

huangapple
  • 本文由 发表于 2020年1月4日 01:18:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/59582704.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定