Skip to content

Commit 07b2391

Browse files
committed
review fixes
1 parent 5c42d1b commit 07b2391

File tree

3 files changed

+132
-121
lines changed

3 files changed

+132
-121
lines changed

code/c/13-quick_sort.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313
int partition(int arr[], int low, int high) {
1414
int pivot = arr[high]; // Choose the last element as pivot
15-
int i = low; // Index of smaller element
15+
int i = low - 1; // Index of smaller element
1616

1717
for (int j = low; j <= high - 1; j++) {
1818
// If current element is smaller than or equal to pivot
@@ -24,11 +24,11 @@ int partition(int arr[], int low, int high) {
2424
arr[j] = temp;
2525
}
2626
}
27-
// Swap arr[i] and arr[high] (or pivot)
28-
int temp = arr[i];
29-
arr[i] = arr[high];
27+
// Swap arr[i + 1] and arr[high] (or pivot)
28+
int temp = arr[i + 1];
29+
arr[i + 1] = arr[high];
3030
arr[high] = temp;
31-
return i;
31+
return i + 1;
3232
}
3333

3434
/**

slides/slides-pt.typ

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ Blank space can be filled with vertical spaces like #v(1fr).
120120
- Inserção e remoção em uma fila
121121
- $O(log n)$ (complexidade *logarítmica*):
122122
- Busca binária
123-
- Inserção e remoção em uma árvore binária de busca
123+
- Inserção e remoção em uma árvore binária de busca balanceada
124124

125125
#pagebreak()
126126

@@ -129,7 +129,7 @@ Blank space can be filled with vertical spaces like #v(1fr).
129129
- Percorrer uma lista encadeada
130130
- Comparar duas _strings_
131131
- $O(n log n)$ (complexidade *log-linear*):
132-
- Algoritmo de ordenação _Quick Sort_
132+
- Algoritmo de ordenação _Quick Sort_ (caso médio)
133133
- Algoritmo de ordenação _Merge Sort_
134134

135135
#pagebreak()
@@ -138,6 +138,7 @@ Blank space can be filled with vertical spaces like #v(1fr).
138138
- Percorrer uma matriz
139139
- Algoritmo de ordenação _Bubble Sort_
140140
- Algoritmo de ordenação _Insertion Sort_
141+
- Algoritmo de ordenação _Quick Sort_ (pior caso)
141142
- $O(n^3)$ (complexidade *cúbica*):
142143
- Multiplicação de matrizes (abordagem ingênua)
143144
- $O(n!)$ (complexidade *fatorial*):
@@ -221,7 +222,7 @@ Grafos podem ser *direcionados* ou *_não_-direcionados*.
221222

222223
== Grafos Ponderados
223224

224-
Grande parte dos grafos são *ponderados*, isto é, possuem valores associados às
225+
Grafos podem ser *ponderados*, isto é, possuem valores associados às
225226
arestas.
226227

227228
#align(horizon + center)[
@@ -499,7 +500,7 @@ $ f: V(G) -> V(H) $
499500

500501
- Custo de espaço $O(n + m)$#footnote[para grafos não-direcionados.]<adjacency-list-cost>
501502
- Custo de construção $O(m)$#footnote(<adjacency-list-cost>)
502-
- Custo de busca de arestas $O(n)$
503+
- Custo de busca de arestas $O("deg"(v))$ (pior caso $O(n)$)
503504
]
504505

505506
== Parte Prática (C ou pseudocódigo)
@@ -521,7 +522,7 @@ $ f: V(G) -> V(H) $
521522
*comprimento* do caminho é o número de arestas que o caminho usa, contando-se
522523
arestas múltiplas vezes.
523524

524-
O *custo* de um caminho num grafo balanceado é a soma dos custos das arestas
525+
O *custo* de um caminho num grafo ponderado é a soma dos custos das arestas
525526
atravessadas.
526527

527528
Dois caminhos são *independentes* se não tiverem nenhum vértice em comum, exceto
@@ -666,7 +667,8 @@ delas), retornando à cidade de origem.
666667

667668
== O que são Árvores?
668669

669-
Árvores são grafos *acíclicos* e *conectados*.
670+
Árvores são grafos não direcionados *conectados* e *acíclicos*.
671+
Uma *árvore enraizada* é obtida ao escolher um vértice como raiz.
670672

671673
#align(horizon + center)[
672674
#figure(
@@ -687,15 +689,16 @@ delas), retornando à cidade de origem.
687689
#pagebreak()
688690

689691
#align(horizon)[
690-
- *Raiz*: o vértice sem arestas entrantes. Todas as árvores têm (apenas) um
691-
vértice raiz.
692-
- *Folha*: vértice sem arestas saindo.
692+
- *Raiz* (árvore enraizada): vértice inicial escolhido. Uma árvore enraizada
693+
possui exatamente uma raiz.
694+
- *Folha* (árvore enraizada): vértice sem filhos (sem arestas saindo na
695+
representação direcionada).
693696
- *Nível*: distância da raiz.
694697
- *Altura*: nível máximo.
695-
- *Pai*: vértice(s) com menor nível (mais próximo da raiz).
696-
- *Filho*: vértice(s) maior nível (mais distante da raiz).
697-
- *Ancestral*: vértice(s) com menor nível.
698-
- *Descendente*: vértice(s) com maior nível.
698+
- *Pai*: vértice adjacente com nível imediatamente menor (exceto para a raiz).
699+
- *Filho*: vértice adjacente com nível imediatamente maior.
700+
- *Ancestral*: vértice no caminho da raiz até um vértice.
701+
- *Descendente*: vértice na subárvore de um vértice.
699702
]
700703

701704
== Subárvores
@@ -909,14 +912,14 @@ e direita é no máximo 1.
909912
== Funções Exponenciais
910913

911914
#align(horizon)[
912-
Uma função é exponencial se ela pode ser reduzida usando notação $O$ para
915+
Uma função tem crescimento exponencial quando pode ser limitada por
913916

914-
$ O(n^m) $
917+
$ O(c^n) $
915918

916-
onde $m$ *_não_* é uma constante positiva.
919+
onde $c > 1$ é uma constante.
917920

918921
Por exemplo, $O(2^n)$ é uma complexidade exponencial#footnote[
919-
note que $n$ não é constante.
922+
o expoente depende de $n$.
920923
].
921924
]
922925

@@ -1012,7 +1015,7 @@ e direita é no máximo 1.
10121015

10131016
[*Relação Conhecida*],
10141017
[$cal(P)$ é um subconjunto de $cal(N P)$.],
1015-
[Não se sabe se $cal(N P)$ é um subconjunto próprio de $cal(P)$ ou se são iguais.],
1018+
[Não se sabe se $cal(P) = cal(N P)$ (ou $cal(P) subset cal(N P)$).],
10161019
)
10171020
]
10181021

@@ -1061,10 +1064,14 @@ e direita é no máximo 1.
10611064
== $cal(N P)$-difíceis
10621065

10631066
#align(horizon)[
1064-
Um problema $cal(N P)$-difícil é um problema para o qual *não se conhece um
1065-
algoritmo eficiente para resolvê-lo*. No entanto, se um algoritmo eficiente para
1066-
um problema $cal(N P)$-difícil for encontrado, então todos os problemas em $cal(N P)$ podem
1067-
ser resolvidos eficientemente.
1067+
Um problema $cal(N P)$-difícil é um problema para o qual todo problema em
1068+
$cal(N P)$ pode ser reduzido em tempo polinomial.
1069+
1070+
#v(1em)
1071+
1072+
Problemas $cal(N P)$-difíceis não precisam ser problemas de decisão (nem estar
1073+
em $cal(N P)$). Se um problema $cal(N P)$-difícil que também esteja em $cal(N P)$
1074+
for resolvido em tempo polinomial, então $cal(P) = cal(N P)$.
10681075
]
10691076

10701077
== $cal(P)$ vs $cal(N P)$-completo e $cal(N P)$-difícil
@@ -1174,7 +1181,7 @@ e direita é no máximo 1.
11741181
- *_Loop_ Aninhado*: complexidade quadrática $O(n^2)$
11751182
- *Recursão*:
11761183
- *Linear*: complexidade linear $O(n)$
1177-
- *Divisória*: complexidade logarítmica $O(log n)$
1184+
- *Divisão e conquista*: tipicamente entre $O(log n)$ e $O(n log n)$ (depende do trabalho por nível)
11781185
- *Binária*: complexidade $O(n log n)$
11791186
- *Exponencial*: complexidade exponencial $O(2^n)$
11801187

@@ -1995,11 +2002,11 @@ e direita é no máximo 1.
19952002
+ $v := Q$.dequeue()
19962003
+ *if* $v = T$
19972004
+ *return* $v$
1998-
+ *for* todas as arestas de $v$ para $w$ *in* $G$.adjacentEdges(v):
1999-
+ *if* $!w$.explored:
2000-
+ $w$.explored $:= "true"$
2001-
+ $w$.parent $:= v$
2002-
+ $Q$.enqueue($w$)
2005+
+ *for* todas as arestas de $v$ para $w$ *in* $G$.adjacentEdges(v):
2006+
+ *if* $!w$.explored:
2007+
+ $w$.explored $:= "true"$
2008+
+ $w$.parent $:= v$
2009+
+ $Q$.enqueue($w$)
20032010
+ *return* _null_
20042011
]
20052012
],
@@ -2013,9 +2020,7 @@ e direita é no máximo 1.
20132020
#align(horizon)[
20142021
#text(size: 7pt)[
20152022
```c
2016-
int bfs(int grafo[][MAX], int inicio, int n) {
2017-
if (inicio->value == T)
2018-
return inicio->id;
2023+
int bfs(int grafo[][MAX], int inicio, int n, int alvo) {
20192024
int visitado[MAX] = {0};
20202025
int fila[MAX], frente = 0, traseira = 0;
20212026
@@ -2024,10 +2029,10 @@ e direita é no máximo 1.
20242029
20252030
while (frente < traseira) {
20262031
int atual = fila[frente++];
2032+
if (atual == alvo)
2033+
return atual;
20272034
20282035
for (int i = 0; i < n; i++) {
2029-
if (atual->value == T)
2030-
return atual->id;
20312036
if (grafo[atual][i] && !visitado[i]) {
20322037
visitado[i] = 1;
20332038
fila[traseira++] = i;
@@ -2117,7 +2122,9 @@ e direita é no máximo 1.
21172122
+ *return* $v$
21182123
+ *for* todas as arestas de $v$ para $w$ *in* $G$.adjacentEdges(v):
21192124
+ *if* $!w$.discovered:
2120-
+ DFS($G$, $w$)
2125+
+ $r := "DFS"(G, w)$
2126+
+ *if* $r \neq "null"$:
2127+
+ *return* $r$
21212128
+ *return* _null_
21222129
]
21232130
],
@@ -2131,14 +2138,16 @@ e direita é no máximo 1.
21312138
#align(horizon)[
21322139
#text(size: 13pt)[
21332140
```c
2134-
int dfs(int grafo[][MAX], int atual, int visitado[], int n) {
2135-
if (atual->value == T)
2136-
return atual->id;
2141+
int dfs(int grafo[][MAX], int atual, int visitado[], int n, int alvo) {
2142+
if (atual == alvo)
2143+
return atual;
21372144
visitado[atual] = 1;
21382145
21392146
for (int i = 0; i < n; i++) {
21402147
if (grafo[atual][i] && !visitado[i]) {
2141-
dfs(grafo, i, visitado, n);
2148+
int encontrado = dfs(grafo, i, visitado, n, alvo);
2149+
if (encontrado != -1)
2150+
return encontrado;
21422151
}
21432152
}
21442153
return -1;
@@ -2705,7 +2714,7 @@ e direita é no máximo 1.
27052714
```c
27062715
int partition(int arr[], int low, int high) {
27072716
int pivot = arr[high]; // pivô
2708-
int i = low; // Índice do menor elemento
2717+
int i = low - 1; // Índice do menor elemento
27092718
27102719
for (int j = low; j <= high - 1; j++) {
27112720
// Se o elemento atual é menor ou igual ao pivô
@@ -2716,12 +2725,12 @@ e direita é no máximo 1.
27162725
arr[j] = temp;
27172726
}
27182727
}
2719-
// Troca arr[i] e arr[high] (ou pivô)
2720-
int temp = arr[i];
2721-
arr[i] = arr[high];
2728+
// Troca arr[i + 1] e arr[high] (ou pivô)
2729+
int temp = arr[i + 1];
2730+
arr[i + 1] = arr[high];
27222731
arr[high] = temp;
27232732
2724-
return i;
2733+
return i + 1;
27252734
}
27262735
```
27272736
]
@@ -3269,18 +3278,14 @@ e direita é no máximo 1.
32693278
digraph Fatorial {
32703279
n4 [label="f(4)"];
32713280
n3 [label="f(3)"];
3272-
n2_1 [label="f(2)"];
3273-
n2_2 [label="f(2)"];
3274-
n1_1 [label="f(1)"];
3275-
n1_2 [label="f(1)"];
3276-
n1_3 [label="f(1)"];
3277-
n0_1 [label="f(0)"];
3278-
n0_2 [label="f(0)"];
3279-
3280-
n4 -> {n3, n2_1};
3281-
n3 -> {n2_2, n1_3};
3282-
n2_1 -> {n1_1, n0_1};
3283-
n2_2 -> {n1_2, n0_2};
3281+
n2 [label="f(2)"];
3282+
n1 [label="f(1)"];
3283+
n0 [label="f(0)"];
3284+
3285+
n4 -> n3;
3286+
n3 -> n2;
3287+
n2 -> n1;
3288+
n1 -> n0;
32843289
}
32853290
```,
32863291
width: 70%,
@@ -3804,7 +3809,7 @@ e direita é no máximo 1.
38043809
#text(size: 13pt)[
38053810
- *Programação Dinâmica:*
38063811
- Resolve subproblemas menores e armazena seus resultados para evitar recomputação.
3807-
- Garante a solução ótima global.
3812+
- Pode garantir a solução ótima global quando a recorrência modela corretamente as restrições.
38083813
- Pode ser mais complexo e consumir mais tempo e espaço.
38093814
- *Algoritmos Gulosos:*
38103815
- Fazem a melhor escolha local sem considerar subproblemas.
@@ -4094,7 +4099,7 @@ e direita é no máximo 1.
40944099
- *Programação Dinâmica:*
40954100
- Considera todas as possibilidades e escolhe a melhor.
40964101
- Armazena resultados de subproblemas para evitar recomputação.
4097-
- Garante a solução ótima global.
4102+
- Pode garantir a solução ótima global quando a recorrência está correta.
40984103
]
40994104
]
41004105

@@ -4117,7 +4122,7 @@ e direita é no máximo 1.
41174122
#align(horizon)[
41184123
#text(size: 14pt)[
41194124
- *Vantagens:*
4120-
- Garante a solução ótima global.
4125+
- Pode garantir a solução ótima global quando o modelo de PD é válido.
41214126
- Evita computações redundantes.
41224127
- *Desafios:*
41234128
- Pode consumir muito tempo e espaço para problemas com grandes entradas.

0 commit comments

Comments
 (0)