Você está na página 1de 162

ALGORITMOS

em linguagem C
Paulo Feolo
Instituto de Matemtica e Estatstica
Universidade de So Paulo
Campus/Elsevier
.
Algoritmos em linguagem C
Paulo Feolo
editora Campus/Elsevier, 2009
www.ime.usp.br/pf/algoritmos-livro/
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 2 / 162
Cincia da computao no a cincia dos computadores,
assim como a astronomia no a cincia dos telescpios.
E. W. Dijkstra
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 3 / 162
Leiaute
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 4 / 162
Leiaute Bom
Bom leiaute
int Funcao (int n, int v[]) {
int i, j;
i = 0;
while (i < n) {
if (v[i] != 0)
i = i + 1;
else {
for (j = i + 1; j < n; j++)
v[j-1] = v[j];
n = n - 1;
}
}
return n;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 5 / 162
Leiaute Mau
Mau leiaute
int Funcao (int n, int v[]) {
int i, j;
i = 0;
while (i < n) {
if (v[i] != 0)
i = i + 1;
else {
for (j = i + 1; j < n; j++)
v[j-1] = v[j];
n = n - 1;
}
}
return n;
}
Use fonte de espaamento fixo!
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 6 / 162
Leiaute Mau
Pssimo leiaute
int Funcao ( int n,int v[] ){
int i,j;
i=0;
while(i<n){
if(v[i] !=0)
i= i +1;
else
{
for (j=i+1;j<n;j++)
v[j-1]=v[j];
n =n- 1;
}
}
return n;
}
Seja consistente!
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 7 / 162
Leiaute Compacto
Um bom leiaute compacto
int Funcao (int n, int v[]) {
int i, j;
i = 0;
while (i < n) {
if (v[i] != 0) i = i + 1;
else {
for (j = i + 1; j < n; j++) v[j-1] = v[j];
n = n - 1; } }
return n; }
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 8 / 162
Leiaute Regras
Regras
Use as regras adotadas por todos os jornais, revistas e livros:
bla bla bla
bla = bla
bla <= bla
bla; bla
bla) bla;
bla {
while (bla
if (bla
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 9 / 162
Leiaute Enfeitado
Leiaute enfeitado
int Funo (int n, int v[]) {
int i, j;
i = 0;
while (i < n) {
if (v[i] != 0)
i = i + 1;
else {
for (j = i + 1; j < n; j++)
v[j-1] = v[j];
n = n - 1;
}
}
return n;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 10 / 162
Leiaute O que eles dizem
Devemos mudar nossa atitude tradicional em relao construo de programas.
Em vez de imaginar que nossa principal tarefa
instruir o computador sobre o que ele deve fazer,
vamos imaginar que nossa principal tarefa
explicar a seres humanos o que queremos que o computador faa.
D. E. Knuth
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 11 / 162
Documentao
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 12 / 162
Documentao O que versus como

documentao: o que um algoritmo faz

cdigo: como o algoritmo faz o que faz


Exemplo
/* A funo abaixo recebe um nmero n >= 1 e um vetor v
* e devolve o valor de um elemento mximo de v[0..n-1].
******************************************************/
int Max (int v[], int n) {
int j, x = v[0];
for (j = 1; j < n; j++)
if (x < v[j]) x = v[j];
return x;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 13 / 162
Invariantes
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 14 / 162
Invariantes Explicam processo iterativo
Exemplo 1
int Max (int v[], int n) {
int j, x;
x = v[0];
for (j = 1; j < n; j++)
/* x um elemento mximo de v[0..j-1] */
if (x < v[j]) x = v[j];
return x;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 15 / 162
Invariantes Explicam processo iterativo
Exemplo 2
int Max (int v[], int n) {
int j, x;
x = v[0];
for (j = 1; /* A */ j < n; j++)
if (x < v[j]) x = v[j];
return x;
}
/* a cada passagem pelo ponto A,
x um elemento mximo de v[0..j-1] */
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 16 / 162
Invariantes O que eles dizem
A atividade de programao deve ser encarada
como um processo de criao de obras de literatura,
escritas para serem lidas.
D. E. Knuth
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 17 / 162
Recurso
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 18 / 162
Recurso
Para entender recurso,
preciso primeiro entender recurso.
folclore
Ao tentar resolver o problema,
encontrei obstculos dentro de obstculos.
Por isso, adotei uma soluo recursiva.
um aluno
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 19 / 162
Recurso Instncias de problemas
Problemas e suas instncias

instncia de um problema = exemplo concreto do problema

cada conjunto de dados de um problema dene uma instncia

cada instncia tem um tamanho


Exemplo
Problema: Calcular a mdia de dois nmeros, digamos a e b.
Instncia: Calcular a mdia de 123 e 9876.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 20 / 162
Recurso Algoritmos recursivos
Problemas que tm estrutura recursiva
Cada instncia do problema
contm uma instncia menor do mesmo problema.
Algoritmo recursivo
se a instncia em questo pequena
resolva-a diretamente
seno
reduza-a a uma instncia menor do mesmo problema
aplique o mtodo instncia menor
volte instncia original
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 21 / 162
Recurso Exemplo
Exemplo: Problema do mximo
Determinar o valor de um elemento mximo de um vetor v[0 . . n1].

o tamanho de uma instncia deste problema n

o problema s faz sentido quando n 1


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 22 / 162
Recurso Exemplo
Soluo recursiva
/* Ao receber v e n >= 1, esta funo devolve
o valor de um elemento mximo de v[0..n-1]. */
int MximoR (int v[], int n) {
if (n == 1)
return v[0];
else {
int x;
x = MximoR (v, n - 1);
if (x > v[n-1])
return x;
else
return v[n-1];
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 23 / 162
Recurso Exemplo
Outra soluo recursiva
int Mximo (int v[], int n) {
return MaxR (v, 0, n);
}
int MaxR (int v[], int i, int n) {
if (i == n-1) return v[i];
else {
int x;
x = MaxR (v, i + 1, n);
if (x > v[i]) return x;
else return v[i];
}
}
/* A funo MaxR recebe v, i e n tais que i < n
e devolve o valor de um elemento mximo de v[i..n-1]. */
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 24 / 162
Vetores
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 25 / 162
Vetores Busca
Problema da busca
Dado x e vetor v[0 . . n1], encontrar um ndice k tal que v[k] = x.
x 987
0 n1
v 222 555 111 333 444 666 555 888 777 987 654

o problema faz sentido com qualquer n 0

se n = 0, o vetor vazio e essa instncia no tem soluo

como indicar que no h soluo?


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 26 / 162
Vetores Busca
Algoritmo de busca
Recebe um nmero x e um vetor v[0 . . n1] com n 0
e devolve k no intervalo 0 . . n1 tal que v[k] = x.
Se tal k no existe, devolve 1.
int Busca (int x, int v[], int n) {
int k;
k = n - 1;
while (k >= 0 && v[k] != x)
k -= 1;
return k;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 27 / 162
Vetores Busca
Deselegante e/ou ineciente!
int k = n - 1, achou = 0;
while (k >= 0 && achou == 0) {
if (v[k] == x) achou = 1;
else k -= 1;
}
return k;
int k;
if (n == 0) return -1;
k = n - 1;
while (k >= 0 && v[k] != x) k -= 1;
return k;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 28 / 162
Vetores Busca
Deselegante, ineciente e/ou errado!
int k = 0;
int sol = -1;
for (k = n-1; k >= 0; k--)
if (v[k] == x) sol = k;
return sol;
int k = n - 1;
while (v[k] != x && k >= 0)
k -= 1;
return k;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 29 / 162
Vetores Busca
Algoritmo recursivo de busca
Recebe x, v e n 0 e devolve k tal que 0 k < n e v[k] = x.
Se tal k no existe, devolve 1.
int BuscaR (int x, int v[], int n) {
if (n == 0) return -1;
if (x == v[n-1]) return n - 1;
return BuscaR (x, v, n - 1);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 30 / 162
Vetores Busca
Deselegante!
int feio (int x, int v[], int n) {
if (n == 1) {
if (x == v[0]) return 0;
else return -1;
}
if (x == v[n-1]) return n - 1;
return feio (x, v, n - 1);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 31 / 162
Vetores Remoo
Problema de remoo
Remover o elemento de ndice k de um vetor v[0 . . n1].
Decises de projeto:

suporemos 0 k n 1

novo vetor ca em v[0 . . n2]

algoritmo devolve algo?


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 32 / 162
Vetores Remoo
Algoritmo de remoo
Remove o elemento de ndice k do vetor v[0 . . n1]
e devolve o novo valor de n. Supe 0 k < n.
int Remove (int k, int v[], int n) {
int j;
for (j = k; j < n-1; j++)
v[j] = v[j+1];
return n - 1;
}

funciona bem mesmo quando k = n 1 ou k = 0

exemplo de uso: n = Remove (51, v, n);


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 33 / 162
Vetores Remoo
Verso recursiva
int RemoveR (int k, int v[], int n) {
if (k == n-1) return n - 1;
else {
v[k] = v[k+1];
return RemoveR (k + 1, v, n);
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 34 / 162
Vetores Insero
Problema de insero
Inserir um novo elemento y entre as posies k 1 e k
de um vetor v[0 . . n1].
Decises de projeto:

se k = 0 ento insere no incio

se k = n ento insere no m

novo vetor ca em v[0 . . n+1]


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 35 / 162
Vetores Insero
Algoritmo de insero
Insere y entre as posies k 1 e k do vetor v[0 . . n1]
e devolve o novo valor de n. Supe que 0 k n.
int Insere (int k, int y, int v[], int n) {
int j;
for (j = n; j > k; j--)
v[j] = v[j-1];
v[k] = y;
return n + 1;
}

estamos supondo n < N

exemplo de uso: n = Insere (51, 999, v, n);


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 36 / 162
Vetores Insero
Verso recursiva
int InsereR (int k, int y, int v[], int n) {
if (k == n) v[n] = y;
else {
v[n] = v[n-1];
InsereR (k, y, v, n - 1);
}
return n + 1;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 37 / 162
Vetores Busca seguida de remoo
Problema de busca-e-remoo
Remover todos os elementos nulos de um vetor v[0 . . n1].
Algoritmo
Remove todos os elementos nulos de v[0 . . n1],
deixa o resultado em v[0 . . i1], e devolve o valor de i.
int RemoveZeros (int v[], int n) {
int i = 0, j;
for (j = 0; j < n; j++)
if (v[j] != 0) {
v[i] = v[j];
i += 1;
}
return i;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 38 / 162
Vetores Busca seguida de remoo
Funciona bem mesmo em casos extremos:

quando n vale 0

quando v[0 . . n1] no tem zeros

quando v[0 . . n1] s tem zeros


Invariantes
No incio de cada iterao

i j

v[0 . . i1] o resultado da remoo dos zeros


do vetor v[0 . . j1] original
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 39 / 162
Vetores Busca seguida de remoo
Mau exemplo: deselegante e ineciente
int i = 0, j = 0; /* "j = 0" suprfluo */
while (i < n) {
if (v[i] != 0) i += 1;
else {
for (j = i; j+1 < n; j++) /* ineficiente */
v[j] = v[j+1]; /* ineficiente */
--n;
}
}
return n;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 40 / 162
Vetores Busca seguida de remoo
Verso recursiva
int RemoveZerosR (int v[], int n) {
int m;
if (n == 0) return 0;
m = RemoveZerosR (v, n - 1);
if (v[n-1] == 0) return m;
v[m] = v[n-1];
return m + 1;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 41 / 162
Endereos
e ponteiros
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 42 / 162
Endereos e ponteiros Endereos
Endereos

os bytes da memria so numerados seqencialmente

o nmero de um byte o seu endereo

cada char ocupa 1 byte

cada int ocupa 4 bytes consecutivos

etc.

cada objeto char, int, struct etc. tem um endereo

o endereo de um objeto x &x


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 43 / 162
Endereos e ponteiros Endereos
Exemplo ctcio
char c;
int i;
struct {int x, y;} ponto;
int v[4];
endereos
c 89421
i 89422
ponto 89426
v[0] 89434
v[1] 89438
v[2] 89442

&i vale 89422

&v[3] vale 89446


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 44 / 162
Endereos e ponteiros Ponteiros
Ponteiros

ponteiro um tipo de varivel capaz de armazenar endereos

se p = &x ento dizemos p aponta para x

se p um ponteiro ento *p o valor do objeto apontado por p


89422
60001
9999
89422
r E
p
9999
representao esquemtica
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 45 / 162
Endereos e ponteiros Ponteiros
Exemplo: Um jeito bobo de fazer j = i + 999
int j, i = 888;
int *p;
p = &i;
j = *p + 999;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 46 / 162
Listas
encadeadas
999
r E
999
r E
999
r E
999
r E
999
r E
999
r
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 47 / 162
Listas encadeadas Estrutura da lista
Estrutura de uma clula
struct cel {
int contedo;
struct cel *seg; /* seguinte */
};
999
r E
contedo seg
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 48 / 162
Listas encadeadas Estrutura da lista
Clulas so um novo tipo de dados
typedef struct cel clula;
Denio de uma clula e de um ponteiro para clula
clula c;
clula *p;

contedo da clula:
c.contedo
p-
>
contedo

endereo da clula seguinte:


c.seg
p-
>
seg
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 49 / 162
Listas encadeadas Estrutura da lista
999
r E
999
r E
999
r E
999
r E
999
r E
999
r
ltima clula da lista: p-
>
seg vale NULL
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 50 / 162
Listas encadeadas Estrutura da lista
Exemplos: imprime lista com e sem cabea
O algoritmo imprime o contedo de uma lista lst sem cabea.
void Imprima (clula *lst) {
clula *p;
for (p = lst; p != NULL; p = p-
>
seg)
printf ("%d\n", p-
>
contedo);
}
Imprime o contedo de uma lista lst com cabea.
void Imprima (clula *lst) {
clula *p;
for (p = lst-
>
seg; p != NULL; p = p-
>
seg)
printf ("%d\n", p-
>
contedo);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 51 / 162
Listas encadeadas Busca
Algoritmo de busca
Recebe um inteiro x e uma lista lst com cabea.
Devolve o endereo de uma clula que contm x
ou devolve NULL se tal clula no existe.
clula *Busca (int x, clula *lst) {
clula *p;
p = lst-
>
seg;
while (p != NULL && p-
>
contedo != x)
p = p-
>
seg;
return p;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 52 / 162
Listas encadeadas Busca
Verso recursiva
clula *BuscaR (int x, clula *lst) {
if (lst-
>
seg == NULL)
return NULL;
if (lst-
>
seg-
>
contedo == x)
return lst-
>
seg;
return BuscaR (x, lst-
>
seg);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 53 / 162
Listas encadeadas Remoo
Algoritmo de remoo de uma clula
Recebe o endereo p de uma clula em uma lista
e remove da lista a clula p-
>
seg.
Supe que p = NULL e p-
>
seg = NULL.
void Remove (clula *p) {
clula *lixo;
lixo = p-
>
seg;
p-
>
seg = lixo-
>
seg;
free (lixo);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 54 / 162
Listas encadeadas Insero
Algoritmo de insero de nova clula
Insere uma nova clula em uma lista
entre a clula p e a seguinte (supe p = NULL).
A nova clula ter contedo y.
void Insere (int y, clula *p) {
clula *nova;
nova = malloc (sizeof (clula));
nova-
>
contedo = y;
nova-
>
seg = p-
>
seg;
p-
>
seg = nova;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 55 / 162
Listas encadeadas Busca e remoo
Algoritmo de busca seguida de remoo
Recebe uma lista lst com cabea
e remove da lista a primeira clula que contiver x,
se tal clula existir.
void BuscaERemove (int x, clula *lst) {
clula *p, *q;
p = lst;
q = lst-
>
seg;
while (q != NULL && q-
>
contedo != x) {
p = q;
q = q-
>
seg;
}
if (q != NULL) {
p-
>
seg = q-
>
seg;
free (q);
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 56 / 162
Listas encadeadas Busca e insero
Algoritmo de busca seguida de insero
Recebe lista lst com cabea e insere nova clula contedo y
imediatamente antes da primeira que contiver x.
Se nenhuma clula contiver x, a nova clula ser inserida no m da lista.
void BuscaEInsere (int y, int x, clula *lst) {
clula *p, *q, *nova;
nova = malloc (sizeof (clula));
nova-
>
contedo = y;
p = lst;
q = lst-
>
seg;
while (q != NULL && q-
>
contedo != x) {
p = q;
q = q-
>
seg;
}
nova-
>
seg = q;
p-
>
seg = nova;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 57 / 162
Filas
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 58 / 162
Filas Implementao em vetor
Fila implementada em vetor
0 s t N-1
111 222 333 444 555 666
uma la f[s..t-1]
Remove elemento da la
x = f[s++]; /* x = f[s]; s += 1; */
Insere y na la
f[t++] = y; /* f[t] = y; t += 1; */
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 59 / 162
Filas Distncias em uma rede
Aplicao: distncias em uma rede
0 1 2 3 4 5
0 0 1 0 0 0 0
1 0 0 1 0 0 0
2 0 0 0 0 1 0
3 0 0 1 0 1 0
4 1 0 0 0 0 0
5 0 1 0 0 0 0
s s
s
s
s s
5 0
1
4
2 3

0 1 2 3 4 5
d 2 3 1 0 1 6
O vetor d d as distncias da cidade 3 a cada uma das demais.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 60 / 162
Filas Distncias em uma rede
Algoritmo das distncias
Recebe matriz A que representa as interligaes entre cidades 0, 1, . . . , n 1:
h uma estrada de x a y se e somente se A[x][y] = 1.
Devolve um vetor d tal que d[x] a distncia da cidade o cidade x.
int *Distncias (int **A, int n, int o) {
int *d, x, y;
int *f, s, t;
d = malloc (n * sizeof (int));
for (x = 0; x < n; x++) d[x] = -1;
d[o] = 0;
f = malloc (n * sizeof (int));
processo iterativo
free (f);
return d;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 61 / 162
Filas Distncias em uma rede
processo iterativo
s = 0; t = 1; f[s] = o; /* o entra na fila */
while (s < t) {
x = f[s++]; /* x sai da fila */
for (y = 0; y < n; y++)
if (A[x][y] == 1 && d[y] == -1) {
d[y] = d[x] + 1;
f[t++] = y; /* y entra na fila */
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 62 / 162
Filas Distncias em uma rede
Invariantes (antes de cada comparao s < t)
1. para cada cidade v em f[0 . . t1]
existe um caminho de comprimento d[v] de o a v
cujas cidades esto todas em f[0 . . t1]
2. para cada cidade v de f[0 . . t1]
todo caminho de o a v tem comprimento d[v]
3. toda estrada que comea em f[0 . . s1] termina em f[0 . . t1]
Conseqncia
Para cada v em f[0 . . t1], o nmero d[v] a distncia de o a v.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 63 / 162
Filas Distncias em uma rede
Para provar invariantes 1 a 3, precisamos de mais dois invariantes:
4. d[f[s]] d[f[s+1]] d[f[t1]]
5. d[f[t1]] d[f[s]] + 1
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 64 / 162
Filas Implementao circular
Implementao circular da la
0 t s N-1
444 555 666 111 222 333
uma la f[s..t-1]
Remove elemento da la
x = f[s++];
if (s == N) s = 0;
Insere y na la
f[t++] = y;
if (t == N) t = 0;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 65 / 162
Filas Implementao em lista encadeada
Fila implementada em lista encadeada
typedef struct cel {
int valor;
struct cel *seg;
} clula;
Decises de projeto

lista sem cabea

primeira clula: incio da la

ltima clula: m da la
Fila vazia
clula *s, *t; /* s aponta primeiro elemento da fila */
s = t = NULL; /* t aponta ltimo elemento da fila */
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 66 / 162
Filas Implementao em lista encadeada
Remove elemento da la
Recebe endereos es e et das variveis s e t respectivamente.
Supe que la no est vazia e remove um elemento da la.
Devolve o elemento removido.
int Remove (clula **es, clula **et) {
clula *p;
int x;
p = *es;
/* p aponta o primeiro elemento da fila */
x = p-
>
valor;
*es = p-
>
seg;
free (p);
if (*es == NULL) *et = NULL;
return x;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 67 / 162
Filas Implementao em lista encadeada
Insere elemento na la
Recebe endereos es e et das variveis s e t respectivamente.
Insere um novo elemento com valor y na la.
Atualiza os valores de s e t.
void Insere (int y, clula **es, clula **et) {
clula *nova;
nova = malloc (sizeof (clula));
nova-
>
valor = y;
nova-
>
seg = NULL;
if (*et == NULL) *et = *es = nova;
else {
(*et)-
>
seg = nova;
*et = nova;
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 68 / 162
Pilhas
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 69 / 162
Pilhas Implementao em vetor
Pilha implementada em vetor
0 t N-1
111 222 333 444 555 666 777
uma pilha p[0..t-1]
Remove elemento da pilha
x = p[--t]; /* t -= 1; x = p[t]; */
Insere y na pilha
p[t++] = y; /* p[t] = y; t += 1; */
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 70 / 162
Pilhas Parnteses e chaves
Aplicao: parnteses e chaves

expressao bem-formada: ((){()})

expressao malformada: ({)}


Algoritmo
Devolve 1 se a string s contm uma seqncia bem-formada
e devolve 0 em caso contrrio.
int BemFormada (char s[]) {
char *p; int t;
int n, i;
n = strlen (s);
p = malloc (n * sizeof (char));
processo iterativo
free (p);
return t == 0;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 71 / 162
Pilhas Parnteses e chaves
processo iterativo
t = 0;
for (i = 0; s[i] != \0; i++) {
/* p[0..t-1] uma pilha */
switch (s[i]) {
case ): if (t != 0 && p[t-1] == () --t;
else return 0;
break;
case }: if (t != 0 && p[t-1] == {) --t;
else return 0;
break;
default: p[t++] = s[i];
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 72 / 162
Pilhas Notao posxa
Aplicao: notao posxa
Notao inxa versus posxa
inxa posxa
( A + B * C ) A B C * +
( A * ( B + C ) / D - E ) A B C + * D / E -
( A + B * ( C - D * ( E - F ) - G * H ) - I * 3 ) A B C D E F - * - G H * - * + I 3 * -
( A + B * C / D * E - F ) A B C * D / E * + F -
( A * ( B + ( C * ( D + ( E * ( F + G ) ) ) ) ) ) A B C D E F G + * + * + *
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 73 / 162
Pilhas Notao posxa
Algoritmo
Recebe uma expresso inxa representada por uma string infix
que comea com ( e termina com ) seguido de \0.
Devolve a correspondente expresso posxa.
char *InfixaParaPosfixa (char infix[]) {
char *posfix, x;
char *p; int t;
int n, i, j;
n = strlen (infix);
posfix = malloc (n * sizeof (char));
p = malloc (n * sizeof (char));
processo iterativo
free (p);
posfix[j] = \0;
return posfix;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 74 / 162
Pilhas Notao posxa
processo iterativo
t = 0; p[t++] = infix[0]; /* empilha ( */
for (j = 0, i = 1; /*X*/ infix[i] != \0; i++) {
/* p[0..t-1] uma pilha de caracteres */
switch (infix[i]) {
case (: p[t++] = infix[i]; /* empilha */
break;
case ): while (1) { /* desempilha */
x = p[--t];
if (x == () break;
posfix[j++] = x; }
break;
demais casos
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 75 / 162
Pilhas Notao posxa
demais casos
case +:
case -: while (1) {
x = p[t-1];
if (x == () break;
--t; /* desempilha */
posfix[j++] = x; }
p[t++] = infix[i]; /* empilha */
break;
case *:
case /: while (1) {
x = p[t-1];
if (x == ( || x == + || x == -)
break;
--t;
posfix[j++] = x; }
p[t++] = infix[i];
break;
default: posfix[j++] = infix[i];
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 76 / 162
Pilhas Notao posxa
Aplicao de InfixaParaPosfixa expresso (A*(B*C+D))
Valores das variveis a cada passagem pelo ponto X:
infix[0..i-1] p[0..t-1] posfix[0..j-1]
( (
( A ( A
( A * ( * A
( A * ( ( * ( A
( A * ( B ( * ( A B
( A * ( B * ( * ( * A B
( A * ( B * C ( * ( * A B C
( A * ( B * C + ( * ( + A B C *
( A * ( B * C + D ( * ( + A B C * D
( A * ( B * C + D ) ( * A B C * D +
( A * ( B * C + D ) ) A B C * D + *
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 77 / 162
Pilhas Implementao em lista encadeada
Pilha implementada em lista encadeada
typedef struct cel {
int valor;
struct cel *seg;
} clula;
Decises de projeto

lista com cabea

segunda clula: topo da pilha


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 78 / 162
Pilhas Implementao em lista encadeada
Pilha vazia
clula cabea;
clula *p;
p = &cabea; /* p-
>
seg o topo da pilha */
p-
>
seg = NULL;
Insere
void Empilha (int y, clula *p) {
clula *nova;
nova = malloc (sizeof (clula));
nova-
>
valor = y;
nova-
>
seg = p-
>
seg;
p-
>
seg = nova;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 79 / 162
Pilhas Implementao em lista encadeada
Remove
int Desempilha (clula *p) {
int x; clula *q;
q = p-
>
seg;
x = q-
>
valor;
p-
>
seg = q-
>
seg;
free (q);
return x;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 80 / 162
Busca em vetor ordenado
Problema:
Encontrar um dado nmero x
num vetor crescente v[0 . . n1].
Vetor crescente se v[0] v[1] v[n1].
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 81 / 162
Busca em vetor ordenado O problema
Problema mais geral
Dado x e um vetor crescente v[0 . . n1],
encontrar j tal que v[j1] < x v[j].

0 j n

se j = 0 ento x v[0]

se j = n ento v[n1] < x

imagine v[1] = e v[n] =


0 12
111 222 333 444 555 555 666 777 888 888 888 999 999
Se x = 555 ento j = 4. Se x = 1000 ento j = 13. Se x = 110 ento j = 0.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 82 / 162
Busca em vetor ordenado Busca seqencial
Algoritmo de busca seqencial
Recebe um vetor crescente v[0 . . n1] com n 1 e um inteiro x.
Devolve um ndice j em 0 . . n tal que v[j1] < x v[j].
int BuscaSeqencial (int x, int n, int v[]) {
int j = 0;
while (j < n && v[j] < x) ++j;
return j;
}

invariante: no comeo de cada iterao tem-se v[j1] < x

consumo de tempo: proporcional a n


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 83 / 162
Busca em vetor ordenado Busca binria
Algoritmo de busca binria
Recebe um vetor crescente v[0 . . n1] com n 1 e um inteiro x.
Devolve um ndice j em 0 . . n tal que v[j1] < x v[j].
int BuscaBinria (int x, int n, int v[]) {
int e, m, d;
e = -1; d = n;
while (/*X*/ e < d - 1) {
m = (e + d)/2;
if (v[m] < x) e = m;
else d = m;
}
return d;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 84 / 162
Busca em vetor ordenado Busca binria
Invariante: a cada passagem pelo ponto X temos v[e] < x v[d].
0 e d n1
111 222 333 444 555 555 666 777 888 888 888 999 999
Consumo de tempo

em cada iterao, o tamanho do vetor em jogo d e 1

tamanho do vetor na primeira, segunda, terceira, etc. iteraes:


n, n/2, n/4, . . . , n/2
k
, . . .

nmero total de iteraes:



= log
2
n

consumo de tempo: proporcional a log


2
n
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 85 / 162
Busca em vetor ordenado Busca binria
Verso recursiva
int BuscaBinria2 (int x, int n, int v[]) {
return BuscaBinR (x, -1, n, v);
}
BuscaBinR recebe um vetor crescente v[e . . d] e um x tal que v[e] < x v[d].
Devolve um ndice j no intervalo e+1 . . d tal que v[j1] < x v[j].
int BuscaBinR (int x, int e, int d, int v[]) {
if (e == d-1) return d;
else {
int m = (e + d)/2;
if (v[m] < x)
return BuscaBinR (x, m, d, v);
else
return BuscaBinR (x, e, m, v);
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 86 / 162
ALGORITMOS
DE ORDENAO
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 87 / 162
Ordenao O problema
Problema
Rearranjar os elementos de um vetor v[0 . . n1]
de tal modo que ele que crescente.
Vetor crescente se v[0] v[1] v[n1].
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 88 / 162
Ordenao
Ordenao
por insero
por seleo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 89 / 162
Ordenao Insero
Algoritmo de ordenao por insero
Rearranja o vetor v[0 . . n1] em ordem crescente.
void Insero (int n, int v[]) {
int i, j, x;
for (j = 1; /*A*/ j < n; j++) {
x = v[j];
for (i = j-1; i >= 0 && v[i] > x; i--)
v[i+1] = v[i];
v[i+1] = x;
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 90 / 162
Ordenao Insero
Invariantes: a cada passagem pelo ponto A
1. v[0 . . n1] uma permutao do vetor original
2. o vetor v[0 . . j1] crescente
0 crescente j1 j n1
444 555 555 666 777 222 999 222 999 222 999
Consumo de tempo

proporcional ao nmero de execues de v[i] > x

no pior caso, esse nmero



n1
j=1
j = n(n 1)/2

consumo de tempo total: no mximo n


2
unidades de tempo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 91 / 162
Ordenao Seleo
Algoritmo de seleo
Rearranja o vetor v[0 . . n1] em ordem crescente.
void Seleo (int n, int v[]) {
int i, j, min, x;
for (i = 0; /*A*/ i < n-1; i++) {
min = i;
for (j = i+1; j < n; j++)
if (v[j] < v[min]) min = j;
x = v[i]; v[i] = v[min]; v[min] = x;
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 92 / 162
Ordenao Seleo
Invariantes: a cada passagem pelo ponto A
1. v[0 . . n1] uma permutao do vetor original
2. v[0 . . i1] est em ordem crescente
3. v[i 1] v[j] para j = i, i+1, . . . , n1
0 i1 i n1
110 120 120 130 140 666 999 666 999 666 999
pequenos, crescente grandes
Consumo de tempo

no mximo n
2
unidades de tempo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 93 / 162
Algoritmo Mergesort
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 94 / 162
Mergesort Problema auxiliar
Problema principal
Rearranjar os elementos de um vetor v[0 . . n1]
de tal modo que ele que crescente,
ou seja, de modo que v[0] v[1] v[n1].
Problema auxiliar: intercalao
Rearranjar v[p . . r1] em ordem crescente
sabendo que v[p . . q1] e v[q . . r1] so crescentes.
p q1 q r1
111 333 555 555 777 999 999 222 444 777 888
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 95 / 162
Mergesort Intercalao de vetores ordenados
Algoritmo de intercalao
Recebe vetores crescentes v[p . . q1] e v[q . . r1]
e rearranja v[p . . r1] em ordem crescente.
void Intercala (int p, int q, int r, int v[]) {
int i, j, k, *w;
w = malloc ((r-p) * sizeof (int));
i = p; j = q; k = 0;
while (i < q && j < r) {
if (v[i] <= v[j]) w[k++] = v[i++];
else w[k++] = v[j++];
}
while (i < q) w[k++] = v[i++];
while (j < r) w[k++] = v[j++];
for (i = p; i < r; i++) v[i] = w[i-p];
free (w);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 96 / 162
Mergesort Intercalao de vetores ordenados
Consumo de tempo do algoritmo Intercala

proporcional ao nmero de elementos do vetor


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 97 / 162
Mergesort Algoritmo principal
Algoritmo Mergesort (ordena por intercalao)
Rearranja o vetor v[p . . r1] em ordem crescente.
void Mergesort (int p, int r, int v[]) {
if (p < r - 1) {
int q = (p + r)/2;
Mergesort (p, q, v);
Mergesort (q, r, v);
Intercala (p, q, r, v);
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 98 / 162
Mergesort Algoritmo principal
0 1 2 3 4 5 6 7 8 9 10
999 111 222 999 888 333 444 777 555 666 555
999 111 222 999 888 333 444 777 555 666 555
999 111 222 999 888 333 444 777 555 666 555
.
.
.
111 999 222 888 999 333 444 777 555 555 666
111 222 888 999 999 333 444 555 555 666 777
111 222 333 444 555 555 666 777 888 999 999
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 99 / 162
Mergesort Algoritmo principal
v[0 . . n1]
v[0 . .
n
2
1] v[
n
2
. . n1]
v[0 . .
n
4
1] v[
n
4
. .
n
2
1] v[
n
2
. .
3n
4
1] v[
3n
4
. . n1]
.
.
.
Consumo de tempo do Mergesort

aproximadamente log
2
n rodadas

cada rodada consome n unidades de tempo

total: n log
2
n unidades de tempo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 100 / 162
Mergesort Algoritmo principal
Verso iterativa
void MergesortI (int n, int v[]) {
int p, r, b = 1;
while (b < n) {
p = 0;
while (p + b < n) {
r = p + 2*b;
if (r > n) r = n;
Intercala (p, p + b, r, v);
p = p + 2*b;
}
b = 2*b;
}
}
0 p p+b p+2b n1
111 999 222 999 333 888 444 777 555 666 555
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 101 / 162
Algoritmo Heapsort
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 102 / 162
Heapsort Heap
Problema
Rearranjar os elementos de um vetor v[0 . . n1]
em ordem crescente.
Denio
Um max-heap um vetor v[1 . . m] tal que v[

1
2
f

] v[f]
para f = 2, 3, . . . , m.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
999 888 666 333 777 555 555 333 222 111 444 111 222 444 111
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 103 / 162
Heapsort Heap
1
2 3
4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 104 / 162
Heapsort Algoritmo auxiliar 1
Algoritmo auxiliar 1: insero em um heap
Transforma v[1 . . m+1] em max-heap supondo que v[1 . . m] max-heap.
void InsereEmHeap (int m, int v[]) {
int f = m+1;
while /*X*/ (f > 1 && v[f/2] < v[f]) {
int t = v[f/2]; v[f/2] = v[f]; v[f] = t;
f = f/2;
}
}

invariante no pto X: v[

1
2
i

] v[i] para i = 2, . . . , m+1, i = f

consumo: log
2
(m + 1) unidades de tempo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 105 / 162
Heapsort Algoritmo auxiliar 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14
98 97 96 95 94 93 92 91 90 89 87 86 85 99
98 97 96 95 94 93 99 91 90 89 87 86 85 92
98 97 99 95 94 93 96 91 90 89 87 86 85 92
99 97 98 95 94 93 96 91 90 89 87 86 85 92
Transforma v[1 . . 14] em max-heap
supondo que v[1 . . 13] max-heap.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 106 / 162
Heapsort Algoritmo auxiliar 2
Algoritmo auxiliar 2
Transforma quase-max-heap v[1 . . m] em max-heap.
void SacodeHeap (int m, int v[]) {
int t, f = 2;
while /*X*/ (f <= m) {
if (f < m && v[f] < v[f+1]) ++f;
if (v[f/2] >= v[f]) break;
t = v[f/2]; v[f/2] = v[f]; v[f] = t;
f *= 2;
}
}

v[1 . . m] quase-max-heap se v[

1
2
f

] v[f] para f = 4, 5, . . . , m

invariante no ponto X: v[

1
2
i

] v[i] quando i = f e i = f+1

consumo: log
2
m unidades de tempo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 107 / 162
Heapsort Algoritmo principal
Algoritmo Heapsort
Rearranja vetor v[1 . . n] de modo que ele que crescente.
void Heapsort (int n, int v[]) {
int m;
for (m = 1; m < n; m++)
InsereEmHeap (m, v);
for (m = n; /*X*/ m > 1; m--) {
int t = v[1]; v[1] = v[m]; v[m] = t;
SacodeHeap (m-1, v);
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 108 / 162
Heapsort Algoritmo principal
Invariantes no ponto X

v[1 . . m] um max-heap

v[1 . . m] v[m+1 . . n]

v[m+1 . . n] est em ordem crescente


1 max-heap m crescente n
777 777 666 444 222 111 444 333 777 888 888 999 999
elementos pequenos elementos grandes
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 109 / 162
Heapsort Algoritmo principal
Consumo de tempo do Heapsort

no pior caso: nlog


2
n unidades de tempo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 110 / 162
Algoritmo Quicksort
Problema:
Rearranjar um vetor v[0 . . n1]
em ordem crescente.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 111 / 162
Quicksort Subproblema da separao
Subproblema da separao: formulao vaga
Rearranjar um vetor v[p . . r] de modo que
os elementos pequenos quem todos do lado esquerdo
e os grandes do lado direito.
Formulao concreta
Rearranjar v[p . . r] de modo que v[p . . j1] v[j] < v[j+1 . . r]
para algum j em p . . r.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 112 / 162
Quicksort Subproblema da separao
Algoritmo da separao
Recebe um vetor v[p . . r] com p r.
Rearranja os elementos do vetor e
devolve j em p . . r tal que v[p . . j1] v[j] < v[j+1 . . r].
int Separa (int p, int r, int v[]) {
int c, j, k, t;
c = v[r]; j = p;
for (k = p; /*A*/ k < r; k++)
if (v[k] <= c) {
t = v[j], v[j] = v[k], v[k] = t;
j++;
}
v[r] = v[j], v[j] = c;
return j;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 113 / 162
Quicksort Subproblema da separao
Invariantes no ponto A

v[p . . r] uma permutao do vetor original

v[p . . j1] c < v[j . . k1] e v[r] = c

p j k r
p j k r
c c c > c > c > c ? ? ? = c
j k
c c c c > c > c > c > c > c = c
j
c c c c = c > c > c > c > c > c
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 114 / 162
Quicksort Subproblema da separao
j k
c c c c > c > c > c > c > c = c
ltima passagem pelo ponto A
j
c c c c = c > c > c > c > c > c
resultado nal
Consumo de tempo do algoritmo Separa
proporcional ao nmero de elementos do vetor
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 115 / 162
Quicksort Algoritmo principal
Algoritmo Quicksort
Rearranja o vetor v[p . . r], com p r + 1,
de modo que ele que em ordem crescente.
void Quicksort (int p, int r, int v[]) {
int j;
if (p < r) {
j = Separa (p, r, v);
Quicksort (p, j - 1, v);
Quicksort (j + 1, r, v);
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 116 / 162
Quicksort Algoritmo principal
Consumo de tempo do Quicksort

no pior caso: n
2
unidades de tempo

em mdia: nlog
2
n unidades de tempo
n := r p + 1
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 117 / 162
Quicksort Altura da pilha de execuo
Quicksort com controle da altura da pilha de execuo
Cuida primeiro do menor dos subvetores v[p . . j1] e v[j+1 . . r].
void QuickSortP (int p, int r, int v[]) {
int j;
while (p < r) {
j = Separa (p, r, v);
if (j - p < r - j) {
QuickSortP (p, j - 1, v);
p = j + 1;
} else {
QuickSortP (j + 1, r, v);
r = j - 1;
}
}
}
Altura da pilha de execuo: log
2
n
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 118 / 162
Algoritmos
de enumerao
Enumerar = fazer uma lista
de todos os objetos de um determinado tipo
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 119 / 162
Algoritmos de enumerao Enumerao de subseqncias
Problema
Fazer uma lista, sem repeties, de todas as subseqncias de 1, 2, . . . , n.
1
1 2
1 2 3
1 2 3 4
1 2 4
1 3
1 3 4
1 4
2
2 3
2 3 4
2 4
3
3 4
4
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 120 / 162
Algoritmos de enumerao Ordem lexicogrca
Ordem lexicogrca de seqncias
r
1
, r
2
, . . . , r
j
precede s
1
, s
2
, . . . , s
k
se
1. j < k e r
1
, . . . , r
j
= s
1
, . . . , s
j
ou
2. existe i tal que r
1
, . . . , r
i1
= s
1
, . . . , s
i1
e r
i
< s
i
Algoritmo de enumerao em ordem lexicogrca
Recebe n 1 e imprime todas as subseqncias no-vazias de 1, 2, . . . , n
em ordem lexicogrca.
void SubseqLex (int n) {
int *s, k;
s = malloc ((n+1) * sizeof (int));
processo iterativo
free (s);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 121 / 162
Algoritmos de enumerao Ordem lexicogrca
processo iterativo
s[0] = 0; k = 0;
while (1) {
if (s[k] < n) {
s[k+1] = s[k] + 1;
k += 1;
} else {
s[k-1] += 1;
k -= 1;
}
if (k == 0) break;
imprima (s, k);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 122 / 162
Algoritmos de enumerao Ordem lexicogrca
Invariante
Cada iterao comea com subseqncia s
1
, s
2
, . . . , s
k
de 1, 2, . . . , n.
k
0 1 2 3 4 5 6 7
0 2 4 5 7 8 ? ?
Vetor s no incio de uma iterao
de SubseqLex com n = 7.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 123 / 162
Algoritmos de enumerao Ordem lexicogrca
Verso recursiva
void SubseqLex2 (int n) {
int *s;
s = malloc ((n+1) * sizeof (int));
SseqR (s, 0, 1, n);
free (s);
}
void SseqR (int s[], int k, int m, int n) {
if (m <= n) {
s[k+1] = m;
imprima (s, k+1);
SseqR (s, k+1, m+1, n); /* inclui m */
SseqR (s, k, m+1, n); /* no inclui m */
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 124 / 162
Algoritmos de enumerao Ordem lexicogrca especial
Ordem lexicogrca especial
r
1
, r
2
, . . . , r
j
precede s
1
, s
2
, . . . , s
k
se
1. j > k e r
1
, . . . , r
k
= s
1
, . . . , s
k
ou
2. existe i tal que r
1
, . . . , r
i1
= s
1
, . . . , s
i1
e r
i
< s
i
1 2 3 4
1 2 3
1 2 4
1 2
1 3 4
1 3
1 4
1
2 3 4
2 3
2 4
2
3 4
3
4
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 125 / 162
Algoritmos de enumerao Ordem lexicogrca especial
Algoritmo de enumerao em ordem lexicogrca especial
Recebe n 1 e imprime, em ordem lexicogrca especial,
todas as subseqncias no-vazias de 1, 2, . . . , n.
void SubseqLexEsp (int n) {
int *s, k;
s = malloc ((n+1) * sizeof (int));
processo iterativo
free (s);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 126 / 162
Algoritmos de enumerao Ordem lexicogrca especial
processo iterativo
s[1] = 0; k = 1;
while (1) {
if (s[k] == n) {
k -= 1;
if (k == 0) break;
} else {
s[k] += 1;
while (s[k] < n) {
s[k+1] = s[k] + 1;
k += 1;
}
}
imprima (s, k);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 127 / 162
Algoritmos de enumerao Ordem lexicogrca especial
Verso recursiva
Recebe n 1 e imprime todas as subseqncias de 1, 2, . . . , n
em ordem lexicogrca especial.
void SubseqLexEsp2 (int n) {
int *s;
s = malloc ((n+1) * sizeof (int));
SseqEspR (s, 0, 1, n);
free (s);
}
continua. . .
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 128 / 162
Algoritmos de enumerao Ordem lexicogrca especial
continuao
Recebe um vetor s[1 . . k] e imprime, em ordem lexicogrca especial,
todas as seqncias da forma s[1], . . . , s[k], t[k+1], . . .
tais que t[k+1], . . . uma subseqncia de m, m+1, . . . , n.
Em seguida, imprime a seqncia s[1], . . . , s[k].
void SseqEspR (int s[], int k, int m, int n) {
if (m > n) imprima (s, k);
else {
s[k+1] = m;
SseqEspR (s, k+1, m+1, n); /* inclui m */
SseqEspR (s, k, m+1, n); /* no inclui m */
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 129 / 162
Algoritmos de enumerao Ordem lexicogrca especial
2 4 7 8 9
2 4 7 8
2 4 7 9
2 4 7
2 4 8 9
2 4 8
2 4 9
2 4 9
2 4
Resultado de SseqEspR (s,2,7,9)
supondo s[1] = 2 e s[2] = 4.
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 130 / 162
Busca de palavras
em um texto
Problema:
Encontrar as ocorrncias de a[1 . . m] em b[1 . . n].
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 131 / 162
Busca de palavras Exemplos
a l g o r t i m o
O s a l g o r t i m o s d e o r d e n a o

3 1 4 1 5 9
3 1 3 1 4 3 1 4 1 3 1 4 1 5 9 3 1 4 1 5 9 2 6 3 1 4

T A C T A
G T A G T A T A T A T A T A T A C T A C T A G T A G

P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 132 / 162
Busca de palavras O problema
Denies

a[1 . . m] suxo de b[1 . . k] se


m k e a[1 . . m] = b[km+1 . . k]

a[1 . . m] ocorre em b[1 . . n] se


existe k no intervalo m. . n tal que a[1 . . m] suxo de b[1 . . k]
Problema
Encontrar o nmero de ocorrncias de a[1 . . m] em b[1 . . n].
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 133 / 162
Busca de palavras O problema
typedef unsigned char *palavra;
typedef unsigned char *texto;
Algoritmo trivial
Recebe palavra a[1 . . m] e texto b[1 . . n], com m 1 e n 0,
e devolve o nmero de ocorrncias de a em b.
int trivial (palavra a, int m, texto b, int n) {
int k, r, ocorrs;
ocorrs = 0;
for (k = m; k <= n; k++) {
r = 0;
while (r < m && a[m-r] == b[k-r]) r += 1;
if (r >= m) ocorrs += 1;
}
return ocorrs;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 134 / 162
Busca de palavras Primeiro algoritmo de BoyerMoore
Algoritmo de BoyerMoore
B C B A
X C B A B X C B A A X B C B A B X

posies k em que a[1 . . 4] comparada com b[k3 . . k]
1 2 3 4
B C B A
c ? @ A B C D E F G
T1[c] 4 4 0 1 2 4 4 4 4
Tabela de deslocamentos T1
T1[c] o menor t em 0 . . m1 tal que a[mt] = c
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 135 / 162
Busca de palavras Primeiro algoritmo de BoyerMoore
Primeiro algoritmo de BoyerMoore
Recebe uma palavra a[1 . . m] e um texto b[1 . . n], com m 1 e n 0,
e devolve o nmero de ocorrncias de a em b.
Supe que cada elemento de a e b pertence ao conjunto de caracteres 0..255.
int BoyerMoore1 (palavra a, int m, texto b, int n) {
int T1[256], i, k, r, ocorrs;
/* pr-processamento da palavra a */
for (i = 0; i < 256; i++) T1[i] = m;
for (i = 1; i <= m; i++) T1[a[i]] = m - i;
busca da palavra a no texto b
return ocorrs;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 136 / 162
Busca de palavras Primeiro algoritmo de BoyerMoore
busca da palavra a no texto b
ocorrs = 0; k = m;
while (k <= n) {
r = 0;
while (m- r >= 1 && a[m-r] == b[k-r]) r += 1;
if (m- r < 1) ocorrs += 1;
if (k == n) k += 1;
else k += T1[b[k+1]] + 1;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 137 / 162
Busca de palavras Segundo algoritmo de BoyerMoore
Segundo algoritmo de BoyerMoore
Tabela de deslocamentos T2
T2[i] o menor t em 1 . . m1 tal que mt bom para i
j bom para i se a[i . . m] suxo de a[1 . . j]
ou a[1 . . j] suxo de a[i . . m]
1 2 3 4 5 6
C A A B A A
i 6 5 4 3 2 1
T2[i] 1 3 6 6 6 6
1 2 3 4 5 6 7 8
B A - B A . B A
i 8 7 6 5 4 3 2 1
T2[i] 3 3 6 6 6 6 6 6
1 2 3 4 5 6 7 8 9 10 11
B A - B A * B A * B A
i 11 10 9 8 7 6 5 4 3 2 1
T2[i] 3 3 3 3 3 9 9 9 9 9 9
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 138 / 162
Busca de palavras Segundo algoritmo de BoyerMoore
Segundo algoritmo de BoyerMoore
Recebe uma palavra a[1 . . m] com 1 m MAX e um texto b[1 . . n]
e devolve o nmero de ocorrncias de a em b.
int BoyerMoore2 (palavra a, int m, texto b, int n) {
int T2[MAX], i, j, k, r, ocorrs;
/* pr-processamento da palavra a */
for (i = m; i >= 1; i--) {
j = m-1; r = 0;
while (m- r >= i && j - r >= 1)
if (a[m-r] == a[j-r]) r += 1;
else j -= 1, r = 0;
T2[i] = m - j;
}
busca da palavra a no texto b
return ocorrs;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 139 / 162
Busca de palavras Segundo algoritmo de BoyerMoore
busca da palavra a no texto b
ocorrs = 0; k = m;
while (k <= n) {
r = 0;
while (m- r >= 1 && a[m-r] == b[k-r]) r += 1;
if (m- r < 1) ocorrs += 1;
if (r == 0) k += 1;
else k += T2[m-r+1];
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 140 / 162
Busca de palavras Segundo algoritmo de BoyerMoore
Consumo de tempo dos algoritmos de BoyerMoore

pr-processamento: m
2
unidades de tempo

busca, pior caso: mn unidades de tempo

busca, em mdia: n unidades de tempo


P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 141 / 162
rvores binrias
s
s s
s s s s
s s s

-
`
`
`

-
`
`
`

-
`
`
`
`
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 142 / 162
rvores binrias Denio
Estrutura de um n
struct cel {
int contedo;
struct cel *esq;
struct cel *dir;
};
typedef struct cel n;
999
contedo
esq dir
r

r
e
e
e
typedef n *rvore;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 143 / 162
rvores binrias Varredura esquerda-raiz-direita
Varredura esquerda-raiz-direita
Visite

a subrvore esquerda (em ordem e-r-d)

depois a raiz

depois a subrvore direita (em ordem e-r-d)


s
5
s
3
s
8
s
1
s
4
s
6
s
9
s
0
s
2
s
7

-
`
`
`

-
`
`
`

-
`
`
`
`
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 144 / 162
rvores binrias Varredura esquerda-raiz-direita
Algoritmo de varredura e-r-d
Recebe uma rvore binria r
e imprime o contedo de seus ns em ordem e-r-d.
void Erd (rvore r) {
if (r != NULL) {
Erd (r-
>
esq);
printf ("%d\n", r-
>
contedo);
Erd (r-
>
dir);
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 145 / 162
rvores binrias Varredura esquerda-raiz-direita
Verso iterativa
void ErdI (rvore r) {
n *p[100], *x;
int t = 0;
x = r;
while (x != NULL || t > 0) {
/* o topo da pilha p[0..t-1] est em t-1 */
if (x != NULL) {
p[t++] = x;
x = x-
>
esq;
}
else {
x = p[--t];
printf ("%d\n", x-
>
contedo);
x = x-
>
dir;
}
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 146 / 162
rvores binrias Altura
Altura

de n = distncia entre n e seu descendente mais afastado

de rvore = altura da raiz


Se rvore tem n ns e altura h ento log
2
n h < n.
s
s s
s s s s
s s s s s

-
`
`
`

-
`
`
`

-
`
`

-
`
`

-
h = log
2
12 = 3
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 147 / 162
rvores binrias Altura
Algoritmo da altura
Devolve a altura da rvore binria r.
int Altura (rvore r) {
if (r == NULL)
return -1; /* a altura de uma rvore vazia -1 */
else {
int he = Altura (r-
>
esq);
int hd = Altura (r-
>
dir);
if (he < hd) return hd + 1;
else return he + 1;
}
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 148 / 162
rvores binrias N seguinte
Estrutura de n com campo pai
struct cel {
int contedo;
struct cel *pai;
struct cel *esq;
struct cel *dir;
};
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 149 / 162
rvores binrias N seguinte
Algoritmo do n seguinte
Recebe um n x de uma rvore binria cujos ns tm campo pai
e devolve o (endereo do) n seguinte na ordem e-r-d.
A funo supe que x = NULL.
n *Seguinte (n *x) {
if (x-
>
dir != NULL) {
n *y = x-
>
dir;
while (y-
>
esq != NULL) y = y-
>
esq;
return y;
}
while (x-
>
pai != NULL && x-
>
pai-
>
dir == x)
x = x-
>
pai;
return x-
>
pai;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 150 / 162
rvores binrias
de busca
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 151 / 162
rvores de busca Denio
Estrutura de um n
struct cel {
int chave;
int contedo;
struct cel *esq;
struct cel *dir;
};
typedef struct cel n;
rvore de busca: denio
E.chave X.chave D.chave
para todo n X, todo n E na subrvore esquerda de X
e todo n D na subrvore direita de X
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 152 / 162
rvores de busca Busca
Algoritmo de busca
Recebe k e uma rvore de busca r.
Devolve um n cuja chave k ou devolve NULL se tal n no existe.
n *Busca (rvore r, int k) {
if (r == NULL || r-
>
chave == k)
return r;
if (r-
>
chave > k)
return Busca (r-
>
esq, k);
else
return Busca (r-
>
dir, k);
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 153 / 162
rvores de busca Busca
Verso iterativa
while (r != NULL && r-
>
chave != k) {
if (r-
>
chave > k) r = r-
>
esq;
else r = r-
>
dir;
}
return r;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 154 / 162
rvores de busca Insero
n *novo;
novo = malloc (sizeof (n));
novo-
>
chave = k;
novo-
>
esq = novo-
>
dir = NULL;
Algoritmo de insero
Recebe uma rvore de busca r e uma folha avulsa novo.
Insere novo na rvore de modo que a rvore continue sendo de busca
e devolve o endereo da nova rvore.
rvore Insere (rvore r, n *novo) {
n *f, *p;
if (r == NULL) return novo;
processo iterativo
return r;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 155 / 162
rvores de busca Insero
processo iterativo
f = r;
while (f != NULL) {
p = f;
if (f-
>
chave > novo-
>
chave) f = f-
>
esq;
else f = f-
>
dir;
}
if (p-
>
chave > novo-
>
chave) p-
>
esq = novo;
else p-
>
dir = novo;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 156 / 162
rvores de busca Remoo
Algoritmo de remoo da raiz
Recebe uma rvore no-vazia r, remove a raiz da rvore e
rearranja a rvore de modo que ela continue sendo de busca.
Devolve o endereo da nova raiz.
rvore RemoveRaiz (rvore r) {
n *p, *q;
if (r-
>
esq == NULL) q = r-
>
dir;
else {
processo iterativo
}
free (r);
return q;
}
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 157 / 162
rvores de busca Remoo
processo iterativo
p = r; q = r-
>
esq;
while (q-
>
dir != NULL) {
p = q; q = q-
>
dir;
}
/* q o n anterior a r na ordem e-r-d */
/* p o pai de q */
if (p != r) {
p-
>
dir = q-
>
esq;
q-
>
esq = r-
>
esq;
}
q-
>
dir = r-
>
dir;
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 158 / 162
rvores de busca Remoo
Exemplo: antes e depois de RemoveRaiz
s
s s
s s
s s
ss s
s
s s
r
11
2 12
1 4
3
p
6
5
q
10
f
8
7 9

s
s s
s s
s s
ss s
s s
q
10
2 12
1 4
3
p
6
5
f
8
7 9

n f passa a ser o lho direito de p


n q ca no lugar de r
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 159 / 162
rvores de busca Remoo
Remoo do lho esquerdo de x
x-
>
esq = RemoveRaiz (x-
>
esq);
Remoo do lho direito de x
x-
>
dir = RemoveRaiz (x-
>
dir);
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 160 / 162
rvores de busca Desempenho dos algoritmos
Consumo de tempo da busca, insero e remoo

pior caso: proporcional altura da rvore

rvore balanceada: proporcional a log


2
n
n = nmero de ns da rvore
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 161 / 162
Fim
P. Feolo (IME-USP) Algoritmos em C Campus/Elsevier 162 / 162

Você também pode gostar