/// <summary> /// Metodo para calcular o menor caminho de um vertice a outro /// </summary> /// <param name="grafo">Grafo ao qual sera feito a busca</param> /// <param name="vOrigem">Vertice de onde se inicia o calculo</param> /// <param name="vDestino">vertice de destino</param> /// <returns>Resposta, contém um titulo, o caminho percorrido no grafo e o custo da rota</returns> public Resposta MenorCaminho(Grafo grafo, Vertice vOrigem, Vertice vDestino) { List<Vertice> naoVisitados; Dictionary<Vertice, double> distancias = new Dictionary<Vertice, double>(); var anteriores = new Dictionary<string, string>(); Vertice vAtual = vOrigem; foreach (var vertice in grafo.Vertices) { if (vertice == vOrigem) { distancias.Add(vertice, 0.0); } else { distancias.Add(vertice, double.MaxValue); } } naoVisitados = grafo.Vertices; do { double pesoVerticeAtual = distancias[vAtual]; foreach (var aresta in vAtual.ArestasSaindo) { double pesoAresta = distancias[aresta.VerticeDestino]; double pesoTotal = pesoVerticeAtual + aresta.Peso; if (pesoTotal < pesoAresta) { distancias[aresta.VerticeDestino] = pesoTotal; if (anteriores.ContainsKey(aresta.VerticeDestino.Nome)) { anteriores[aresta.VerticeDestino.Nome] = vAtual.Nome; } else { anteriores.Add(aresta.VerticeDestino.Nome, vAtual.Nome); } } } List<Aresta> lsAresta = vAtual.ArestasSaindo; naoVisitados.Remove(vAtual); double menorValor = double.MaxValue; foreach (var aresta in lsAresta) { if (aresta.Peso < menorValor && naoVisitados.Contains(aresta.VerticeDestino)) { menorValor = aresta.Peso; vAtual = aresta.VerticeDestino; } } } while (naoVisitados.Count > 0); Resposta resposta = new Resposta(); string linha = ""; resposta.Linhas.Add(new Linha { TextoLinha = string.Format("MENOR CAMINHO {0} {1}", vOrigem.Nome, vDestino.Nome) }); string anterior = vDestino.Nome; linha += " " + anterior; do { anterior = anteriores[anterior]; linha += " " + anterior; } while (!anterior.Equals(vOrigem.Nome)); resposta.Linhas.Add(new Linha { TextoLinha = InverterString(linha) }); resposta.Linhas.Add(new Linha { TextoLinha = distancias[vDestino].ToString() }); return resposta; }
/// <summary> /// Método para fazer busca em profundidade no grafo /// </summary> /// <param name="grafo">Grafo no qual sera feito a busca</param> /// <param name="vOrigem">vertice de origem</param> /// <param name="vDestino">vertice a ser encontrado no grafo</param> /// <returns>Resposta, contém um tirulo e o caminho percorrido no grafo até encontrar o destino</returns> public Resposta BuscaEmProfundidade(Grafo grafo, Vertice vOrigem, Vertice vDestino) { List<Vertice> visitados = new List<Vertice>(); Stack<Vertice> fronteira = new Stack<Vertice>(); Vertice vAtual = grafo.Vertices.First(x => x.Nome == vOrigem.Nome); Resposta resposta = new Resposta(); Linha linhaResposta; string linha; try { if (vAtual != null) { resposta.Titulo = String.Format("PROFUNDIDADE {0} {1}:", vOrigem.Nome, vDestino.Nome); linhaResposta = new Linha { TextoLinha = vAtual.Nome }; resposta.Linhas.Add(linhaResposta); while (true) { if (!(vAtual == vDestino)) { foreach (var aresta in vAtual.ArestasSaindo.OrderByDescending(x => x.VerticeDestino.Nome)) { fronteira.Push(aresta.VerticeDestino); } visitados.Add(vAtual); //pega o proximo vertice não visitado na fronteira for (int i = 0; i < fronteira.Count - 1; i++) { vAtual = fronteira.Peek(); if (visitados.Contains(vAtual)) { vAtual = fronteira.Pop(); continue; } break; } linha = ""; foreach (var vertice in fronteira) { if (!visitados.Contains(vertice)) { linha += " " + vertice.Nome; } } if (!string.IsNullOrEmpty(linha)) { resposta.Linhas.Add(new Linha { TextoLinha = linha }); } } else { return resposta; } } } else { return null; } } catch (Exception) { throw; } }
/// <summary> /// Método para calcular a distancia de uma rota no grafo /// </summary> /// <param name="grafo">Grafo no qual será calculado a rota</param> /// <param name="rota">rota a ser calculada</param> /// <returns>Resposta, contém um titulo e o custo da rota</returns> public Resposta CalculaDistancia(Grafo grafo, List<Vertice> rota) { if (grafo.Peso) { Resposta resposta = new Resposta(); string linhaResp = "DISTANCIA:"; foreach (var vertice in rota) { linhaResp += " " + vertice.Nome; } resposta.Titulo = linhaResp; Double resultado = 0.0; Aresta aresta; for (int i = 0; i < rota.Count; i++) { if (i != rota.Count - 1) { aresta = rota[i].ArestasSaindo.FirstOrDefault(x => x.VerticeDestino == rota[i + 1]); if (aresta != null) { resultado += aresta.Peso; } } } resposta.Linhas.Add(new Linha { TextoLinha = resultado.ToString() }); return resposta; } return null; }
/// <summary> /// Método para fazer a busca em largura /// </summary> /// <param name="grafo">Grafo no qual será feito a busca</param> /// <param name="vAtual">vertice de onde se inicia a busca</param> /// <param name="vDestino">vertice a ser encontrado no grafo</param> /// <returns>Resposta, contem um titulo e o caminho percorrido até encontrar o vertice</returns> public Resposta BuscaEmLargura(Grafo grafo, Vertice vOrigem, Vertice vDestino) { List<Vertice> fronteira = new List<Vertice>(); List<Vertice> visitados = new List<Vertice>(); Vertice vAtual = grafo.Vertices.First(x => x.Nome == vOrigem.Nome); Resposta resposta = new Resposta(); Linha linhaResposta; string linha; try { resposta.Titulo = String.Format("LARGURA {0} {1}:", vOrigem.Nome, vDestino.Nome); linhaResposta = new Linha { TextoLinha = vAtual.Nome }; resposta.Linhas.Add(linhaResposta); while (true) { if (vAtual != null) { if (!(vAtual == vDestino)) { //adiciona todos os destinos do vertice atual a fronteira foreach (var aresta in vAtual.ArestasSaindo.OrderBy(x => x.VerticeDestino.Nome)) { fronteira.Add(aresta.VerticeDestino); } //adiciona o vertice atual a lista de visitados visitados.Add(vAtual); //pega o proximo vertice não visitado na fronteira for (int i = 0; i < fronteira.Count - 1; i++) { if (!visitados.Contains(fronteira[i])) { vAtual = fronteira[i]; break; } fronteira.Remove(fronteira[i]); } linha = ""; foreach (var vertice in fronteira) { if (!visitados.Contains(vertice)) { linha += " " + vertice.Nome; } } resposta.Linhas.Add(new Linha { TextoLinha = linha }); } else { return resposta; } } else { return null; } } } catch (Exception) { //Erro ao executar o algoritimo throw; } }