Skip to content

Commit 4382a50

Browse files
authored
Merge pull request kelvins#144 from thelostgus/main
Adicionando Estrutura de dados de um Grafo para a linguagem Rust
2 parents 0f96f8b + f37c76d commit 4382a50

File tree

2 files changed

+237
-2
lines changed

2 files changed

+237
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,8 +1907,8 @@ Com o objetivo de alcançar uma abrangência maior e encorajar novas pessoas a c
19071907
</a>
19081908
</td>
19091909
<td> <!-- Rust -->
1910-
<a href="./CONTRIBUTING.md">
1911-
<img align="center" height="25" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg" />
1910+
<a href="./src/rust/grafo.rs">
1911+
<img align="center" height="25" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/rust/rust-plain.svg" />
19121912
</a>
19131913
</td>
19141914
<td> <!-- Elixir -->

src/rust/grafo.rs

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

0 commit comments

Comments
 (0)