Skip to content

Commit e4c5a29

Browse files
committed
Adicionando Estrutura de dados de um Grafo para a linguagem de programação Rust, baseado na Orientação a Objetos do Rust e com alto desempenho avaliado via entregas de atividades envolvendo grafos no beecrowd
1 parent 0f96f8b commit e4c5a29

File tree

1 file changed

+244
-0
lines changed

1 file changed

+244
-0
lines changed

src/rust/grafo.rs

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
Autor: Gustavo Michels de Camargo
3+
4+
Projeto: Algoritmo estrural de um Grafo
5+
6+
7+
*/
8+
9+
10+
use std::{collections::HashMap};
11+
12+
// Matriz de Vector usada ara construir o Grafo.
13+
type MatrizGrafo = Vec<Vec<isize>>;
14+
15+
16+
17+
// O dicionario serve para podermos dar entrada a qualquer String e ter como abstrair suas posições dentro.
18+
// da matriz numerica, isso serve apenas para fins de uso, não requerer transcrever um Nodo com X para valor numerico.
19+
#[derive(PartialEq, Eq, Clone, Debug)]
20+
struct Grafo {
21+
matriz: MatrizGrafo,
22+
dicionario: HashMap<String, usize>,
23+
bicondicional: bool
24+
}
25+
26+
trait Projeto {
27+
// Geral
28+
fn new(tamanho: usize, tipo: &str) -> Grafo;
29+
30+
// Funcçoes envolvendo o dicionario - Usuario
31+
fn usr_pegar_indice(&self, chave: String) -> usize;
32+
fn usr_pegar_chave(&self, indice: usize) -> String;
33+
34+
// Usuario
35+
fn usr_adicionar_conexao(&mut self, a: String, b: String, valor: isize);
36+
fn usr_remover_conexao(&mut self, a: String, b: String);
37+
fn usr_numero_conexoes(&self, no: String) -> usize;
38+
fn usr_verificar_se_existe_conexao(&self, a: String, b: String) -> bool;
39+
fn usr_conexoes(&self, a: String) -> Vec<String>;
40+
41+
// Maquina / uso para os Algoritmos
42+
fn adicionar_conexao(&mut self, a: usize, b: usize, valor: isize);
43+
fn remover_conexao(&mut self, a: usize, b: usize);
44+
fn numero_conexoes(&self, no: usize) -> usize;
45+
fn verificar_se_existe_conexao(&self, a: usize, b: usize) -> bool;
46+
fn conexoes(&self, a: usize) -> Vec<usize>;
47+
48+
// Algoritmos que atuam sobre Grafos
49+
}
50+
51+
52+
// Este é a implementação da "Classe" de um grafo.
53+
impl Projeto for Grafo {
54+
// Tamanho: Numero Maximo de Vertices que a matriz ppode usar de 0 até tamanho.
55+
// Em notação matematica relativa a limites: [0, tamanho).
56+
// Toda função que começa com 'usr_'(usr = usuario) é a versão da função que deve ser usada para interagir diretamente com o usuario.
57+
// As funções de mesmo nome mas sem 'usr_' deve ser usada apenas dentro dos algoritmos, como o Dijkstra para menor caminho entre dois nos.
58+
// Fiz assim para otimizar processamento e descartar necessidade de acessar e
59+
// consultaro dicionario o tempo todo quando se apenas como Objetivo encontrar um menor caminho com Dijkstra por exemplo.
60+
61+
// Apenas essa função foge a regra por ser universal
62+
fn new(tamanho: usize, tipo: &str) -> Grafo {
63+
Grafo {
64+
matriz: vec![vec![-1; tamanho]; tamanho],
65+
dicionario: HashMap::new(),
66+
bicondicional: match tipo {
67+
"->" => false, // Condicional
68+
"<->" | _ => true // Bicondicional
69+
}
70+
}
71+
}
72+
73+
// ---- Funções para uso direto do usuario ----
74+
75+
// Retorna o indice da matriz relacionada a chave
76+
fn usr_pegar_indice(&self, chave: String) -> usize {
77+
if self.dicionario.contains_key(&chave) {
78+
return (&self.dicionario.get(&chave)).unwrap().clone();
79+
}
80+
81+
return 0;
82+
}
83+
84+
// Retorna a chave do dicionario relacionada ao valor do indice da matriz do grafo
85+
fn usr_pegar_chave(&self, indice: usize) -> String {
86+
for (key, value) in self.dicionario.iter() {
87+
if *value == indice {
88+
return (*key).clone();
89+
}
90+
}
91+
92+
return "".to_string();
93+
}
94+
95+
// Conecta Dois vertices
96+
fn usr_adicionar_conexao(&mut self, a: String, b: String, valor: isize) {
97+
if !self.dicionario.contains_key(&a){
98+
let num: usize = self.dicionario.len();
99+
self.dicionario.insert(a.to_owned(), num);
100+
}
101+
102+
if !self.dicionario.contains_key(&b){
103+
let num: usize = self.dicionario.len();
104+
self.dicionario.insert(b.to_owned(), num);
105+
}
106+
107+
let (valor_a, valor_b): (usize, usize) = (self.usr_pegar_indice(a), self.usr_pegar_indice(b));
108+
109+
self.matriz[valor_a][valor_b] = valor;
110+
111+
if self.bicondicional {
112+
self.matriz[valor_b][valor_a] = valor;
113+
}
114+
115+
}
116+
117+
fn usr_remover_conexao(&mut self, a: String, b: String) {
118+
let (valor_a, valor_b): (usize, usize) = (self.usr_pegar_indice(a), self.usr_pegar_indice(b));
119+
120+
self.matriz[valor_a][valor_b] = -1;
121+
self.matriz[valor_b][valor_a] = -1;
122+
}
123+
124+
// Retorba o numero de vertices na qual ele se conecta
125+
fn usr_numero_conexoes(&self, no: String) -> usize {
126+
self.matriz[self.usr_pegar_indice(no)].iter()
127+
.filter(|x| **x >= 0)
128+
.collect::<Vec<&isize>>()
129+
.len() as usize | 0
130+
}
131+
132+
// Verifica se dois nos estão conectados
133+
fn usr_verificar_se_existe_conexao(&self, a: String, b: String) -> bool {
134+
self.matriz[self.usr_pegar_indice(a)][self.usr_pegar_indice(b)] >= 0
135+
}
136+
137+
138+
fn usr_conexoes(&self, a: String) -> Vec<String> {
139+
let mut result: Vec<String> = Vec::new();
140+
let a_value: usize = self.usr_pegar_indice(a);
141+
142+
for i in 0..self.matriz[a_value].len() {
143+
if a_value != i && self.matriz[a_value][i] > -1 {
144+
result.push(self.usr_pegar_chave(i));
145+
}
146+
}
147+
148+
return result;
149+
}
150+
151+
152+
153+
// ---- Funções para uso direto dos algoritmos (tem melhor perfomance) ----
154+
155+
156+
// Retorna um array dos indice de todos os nos na qual o no 'a' se conecta
157+
// Esera usar esta função apenas para usos proprios dentro do Grafo, como em algoritmos tipo dijkstra
158+
// Conecta Dois vertices
159+
fn adicionar_conexao(&mut self, a: usize, b: usize, valor: isize) {
160+
self.matriz[a][b] = valor;
161+
162+
if self.bicondicional {
163+
self.matriz[b][a] = valor;
164+
}
165+
}
166+
167+
fn remover_conexao(&mut self, a: usize, b: usize) {
168+
self.matriz[a][b] = -1;
169+
self.matriz[b][a] = -1;
170+
}
171+
172+
// Retorba o numero de vertices na qual ele se conecta
173+
fn numero_conexoes(&self, no: usize) -> usize {
174+
self.matriz[no].iter()
175+
.filter(|x| **x >= 0)
176+
.collect::<Vec<&isize>>()
177+
.len() as usize | 0
178+
}
179+
180+
fn verificar_se_existe_conexao(&self, a: usize, b: usize) -> bool {
181+
self.matriz[a][b] >= 0
182+
}
183+
184+
fn conexoes(&self, a: usize) -> Vec<usize> {
185+
let mut result: Vec<usize> = Vec::new();
186+
187+
for i in 0..self.matriz[a].len() {
188+
if a != i && self.matriz[a][i] > -1 {
189+
result.push(i);
190+
}
191+
}
192+
return result;
193+
}
194+
195+
196+
// ---- Funções dos algoritmos ----
197+
198+
199+
}
200+
201+
202+
// Main
203+
fn main() {
204+
// Grafo com no maximo mil vertices
205+
// "->" = Grafo condicional, "<->" = Grafo Bicondicional
206+
let mut grafo: Grafo = Grafo::new(1000, "->");
207+
208+
grafo.usr_adicionar_conexao(0.to_string(), 1.to_string(), 1);
209+
grafo.usr_adicionar_conexao(1.to_string(), 2.to_string(), 1);
210+
grafo.usr_adicionar_conexao(2.to_string(), 3.to_string(), 1);
211+
grafo.usr_adicionar_conexao(3.to_string(), 0.to_string(), 1);
212+
213+
println!("{:?}", grafo.conexoes(2));
214+
}
215+
216+
217+
#[cfg(test)]
218+
mod test {
219+
use super::*;
220+
221+
#[test]
222+
fn usr_numero_conexoes() {
223+
let mut grafo: Grafo = Grafo::new(1000, "->");
224+
225+
for i in 1..1000 {
226+
grafo.usr_adicionar_conexao(0.to_string(), i.to_string(), 1);
227+
}
228+
229+
assert_eq!(grafo.usr_numero_conexoes(0.to_string()), 999);
230+
assert_eq!(grafo.usr_numero_conexoes(0.to_string()), grafo.numero_conexoes(0));
231+
}
232+
233+
#[test]
234+
fn numero_conexoes() {
235+
let mut grafo: Grafo = Grafo::new(1000, "<->");
236+
237+
for i in 1..1000 {
238+
grafo.adicionar_conexao(0, i, 1);
239+
}
240+
241+
assert_eq!(grafo.numero_conexoes(0), 999);
242+
assert_eq!(grafo.numero_conexoes(0), grafo.usr_numero_conexoes(0.to_string()));
243+
}
244+
}

0 commit comments

Comments
 (0)