1
+ /*
2
+
3
+ Contribuidores
4
+ - Dromedario de chapeu
5
+
6
+ O Quick Sort, é um dos algoritmos de ordenação padrões de se estudar.
7
+ Ele é famoso por ser relativamente eficiente na maioria dos casos, tendo
8
+ complexidade O(n log n). Porem em casos específicos ele pode chegar a ser
9
+ O(n²) nos piores casos, como a lista estar basicamente invertida por exemplo.
10
+ O Quick Sort adota a estrategia de "dividir e conquistar", que é resumidamente
11
+ dividir a lista em sub 2 listas e organizar essas sub listas. A cada execução
12
+ é escolhido o Pivot, e a partir deste Pivot nos comparamos todos os elementos
13
+ da lista ate encontrar algum valor menor ou igual ao pivot, quando encontrarmos
14
+ este valor, ele é colocado a frente do pivot. Quando passarmos por toda a
15
+ lista, nos fazemos o swap entre o pivot e o ultimo índice que foi coloca a sua
16
+ frene, assim nos teremos a garantia de que todos os itens a esquerda do pivot
17
+ sejam menores, e os a direita maiores. E assim nos pegamos essas 2 novas listas,
18
+ e fazemos o mesmo processo.
19
+
20
+ Recomendo dar uma olhada mais profunda sobre o funcionado e casos específicos,
21
+ como os diferentes métodos de partição e funcionado com múltiplos pivot's, prometo
22
+ que é algo mais interessante e menos chato do que parece.
23
+ Links: https://pt.wikipedia.org/wiki/Quicksort
24
+ https://rosettacode.org/wiki/Sorting_algorithms/Quicksort
25
+
26
+ */
27
+
28
+
29
+ // l = limite esquerdo
30
+ // r = limite direito
31
+ // É preciso indicar esses valores invés de gerar uma nova lista a cada divisão
32
+ // primeiramente para sempre lidarmos com a mesma lista, alterando os seus valores
33
+ // e segundamente porque ficar criando novas listas seria muito custoso em uma recursão
34
+ fn partition ( lista : & mut [ i32 ] , l : usize , r : usize ) -> isize {
35
+ // Declaramos o nosso pivot sendo o primeiro item da lista
36
+ let pivot = lista[ l] ;
37
+
38
+ // Para colocarmos os valores menores ou iguais ao pivot na sua frente
39
+ // precisamos de uma variável pra contar quantos índices a frente colocar
40
+ // o novo valor a frente, para não ficarmos trocando o mesmo valor
41
+ let mut count = l;
42
+
43
+ // For para fazer interação na lista. Não usamos enumerate pois precisamso
44
+ // simular as sub listas
45
+ for j in l + 1 ..r + 1 {
46
+ if lista[ j] <= pivot {
47
+ count += 1 ;
48
+ lista. swap ( count, j) ;
49
+ }
50
+ }
51
+
52
+ // Trocamos o índice de pivot de lugar com o ultimo menor/igual valor, pois
53
+ lista. swap ( l, count) ;
54
+
55
+ // O índice onde apos a troca se encontra o Pivot é retornado, para que sirva
56
+ // como referencia, para as 2 sub listas, 0..count - 1 e count + 1..len serão
57
+ // as novas listas.
58
+ return count as isize ;
59
+ }
60
+
61
+ fn quick_sort ( lista : & mut [ i32 ] , l : isize , r : isize ) {
62
+ // A condição de parda da recuroa é caso tanto o extremo direito quanto esquerdo
63
+ // sejam iguais, ou sejá, a lista so tem 1 elemento
64
+ if l < r {
65
+ let indice_pivot = partition ( lista, l as usize , r as usize ) ;
66
+ quick_sort ( lista, l, indice_pivot - 1 ) ;
67
+ quick_sort ( lista, indice_pivot + 1 , r) ;
68
+ }
69
+ }
70
+
71
+ fn printa ( lista : Vec < i32 > ) {
72
+ for i in lista. iter ( ) {
73
+ print ! ( "{} " , * i) ;
74
+ }
75
+ println ! ( ) ;
76
+ }
77
+
78
+ fn main ( ) {
79
+ let mut lista = vec ! [ 1 , 6 , 3 , 9 , 3 , 8 , 5 , 2 , 7 ] ;
80
+ let len = lista. len ( ) as isize ;
81
+
82
+ printa ( lista. clone ( ) ) ;
83
+ quick_sort ( & mut lista, 0 , len - 1 ) ;
84
+ printa ( lista. clone ( ) ) ;
85
+ }
86
+
87
+ #[ cfg( test) ]
88
+ mod test {
89
+ use crate :: * ;
90
+
91
+ #[ test]
92
+ fn quick ( ) {
93
+ let mut lista = vec ! [ 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 ] ;
94
+ let len = lista. len ( ) as isize - 1 ;
95
+ quick_sort ( & mut lista, 0 , len) ;
96
+ assert_eq ! ( vec![ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] , lista) ;
97
+
98
+ let mut lista = vec ! [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ;
99
+ let len = lista. len ( ) as isize - 1 ;
100
+ quick_sort ( & mut lista, 0 , len) ;
101
+ assert_eq ! ( vec![ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] , lista) ;
102
+ }
103
+ }
0 commit comments