O documento discute busca e ordenação de vetores. Explica busca linear e busca binária, definindo suas entradas, saídas e complexidades. A busca linear tem complexidade O(n), enquanto a busca binária é mais eficiente com complexidade O(log n).
Busca: definição
Entrada:
vetor x,com n elementos
elemento a ser buscado
Saída:
índice (posição) do elemento no vetor
-1, se o elemento não for encontrado
4
Intuição
• Para cadaelemento do vetor:
• Compara com o elemento buscado
• Se o elemento for igual ao buscado,
retorna o índice do elemento
9
32.
Algoritmo (em Python)
defseq(start, stop, step=1):
dir = 1 if (step > 0) else -1
return range(start, stop + dir, step)
10
33.
Algoritmo (em Python)
defbuscaLinear(x, elem):
def seq(start, stop, step=1):
dir = 1 if (step > 0) else -1
return range(start, stop + dir, step)
10
34.
Algoritmo (em Python)
defbuscaLinear(x, elem):
n = len(x)
def seq(start, stop, step=1):
dir = 1 if (step > 0) else -1
return range(start, stop + dir, step)
10
35.
Algoritmo (em Python)
defbuscaLinear(x, elem):
n = len(x)
for i in seq(0, n - 1): # 0, 1, ..., n-1
def seq(start, stop, step=1):
dir = 1 if (step > 0) else -1
return range(start, stop + dir, step)
10
36.
Algoritmo (em Python)
defbuscaLinear(x, elem):
n = len(x)
for i in seq(0, n - 1): # 0, 1, ..., n-1
if x[i] == elem:
def seq(start, stop, step=1):
dir = 1 if (step > 0) else -1
return range(start, stop + dir, step)
10
37.
Algoritmo (em Python)
defbuscaLinear(x, elem):
n = len(x)
for i in seq(0, n - 1): # 0, 1, ..., n-1
if x[i] == elem:
return i
def seq(start, stop, step=1):
dir = 1 if (step > 0) else -1
return range(start, stop + dir, step)
10
38.
Algoritmo (em Python)
defbuscaLinear(x, elem):
n = len(x)
for i in seq(0, n - 1): # 0, 1, ..., n-1
if x[i] == elem:
return i
return -1
def seq(start, stop, step=1):
dir = 1 if (step > 0) else -1
return range(start, stop + dir, step)
10
Complexidade
Melhor caso: 1comparação (elem == x[0])
def buscaLinear(x, elem):
n = len(x)
for i in seq(0, n - 1): # 0, 1, ..., n-1
if x[i] == elem:
return i
return -1
12
43.
Complexidade
Melhor caso: 1comparação (elem == x[0])
Pior caso: n comparações (elem não encontrado)
def buscaLinear(x, elem):
n = len(x)
for i in seq(0, n - 1): # 0, 1, ..., n-1
if x[i] == elem:
return i
return -1
12
44.
Complexidade
Melhor caso: 1comparação (elem == x[0])
Pior caso: n comparações (elem não encontrado)
Caso médio: n/2 comparações
def buscaLinear(x, elem):
n = len(x)
for i in seq(0, n - 1): # 0, 1, ..., n-1
if x[i] == elem:
return i
return -1
12
Complexidade
• O tempode execução da busca linear, no pior
caso, tende a ser proporcional ao número de
elementos, n.
13
47.
Complexidade
• O tempode execução da busca linear, no pior
caso, tende a ser proporcional ao número de
elementos, n.
• Em outras palavras, o tempo de execução é O(n).
13
48.
Complexidade
• O tempode execução da busca linear, no pior
caso, tende a ser proporcional ao número de
elementos, n.
• Em outras palavras, o tempo de execução é O(n).
• O espaço de armazenamento é constante, não
depende do tamanho do vetor.
13
49.
Complexidade
• O tempode execução da busca linear, no pior
caso, tende a ser proporcional ao número de
elementos, n.
• Em outras palavras, o tempo de execução é O(n).
• O espaço de armazenamento é constante, não
depende do tamanho do vetor.
• Em outras palavras, a complexidade de espaço é
O(1).
13
Discussão
Vamos assumir queos elementos do vetor de 1
milhão de elementos estão em ordem crescente.
É possível buscar um elemento com menos de 1
milhão comparações (no pior caso)?
15
54.
Discussão
Vamos assumir queos elementos do vetor de 1
milhão de elementos estão em ordem crescente.
É possível buscar um elemento com menos de 1
milhão comparações (no pior caso)?
Como você busca uma palavra em um
dicionário?
15
Intuição
• Olhar oelemento do meio da lista
Ver animação interativa (buscar 67, 59, 60…)
17
57.
Intuição
• Olhar oelemento do meio da lista
• Comparar com o elemento que estamos buscando
(<, >, =)
Ver animação interativa (buscar 67, 59, 60…)
17
58.
Intuição
• Olhar oelemento do meio da lista
• Comparar com o elemento que estamos buscando
(<, >, =)
• Continuar procurando apenas na metade em que o
elemento pode estar
Ver animação interativa (buscar 67, 59, 60…)
17
Confronto
Entrada: vetor de1 milhão de elementos
Busca linear:
1 milhão de comparações
Busca binária:
21 comparações
22
93.
Confronto
Entrada: vetor de1 milhão de elementos
Busca linear:
1 milhão de comparações
Busca binária:
21 comparações
E se fossem 2 milhões de elementos?
22
Discussão
• Busca bináriaé mais rápida, mas requer vetor
ordenado
• Se você pretende fazer muitas buscas no mesmo
vetor, pode valer a pena ordenar o vetor
23
97.
Discussão
• Busca bináriaé mais rápida, mas requer vetor
ordenado
• Se você pretende fazer muitas buscas no mesmo
vetor, pode valer a pena ordenar o vetor
• Qual a complexidade de se ordenar um vetor?
23
Definição
Entrada:
vetor x, comn elementos
Saída:
vetor x nos quais as posições dos elementos foram
trocadas de forma que
x[0] ≤ x[1] ≤ x[2] ≤ x[3] ≤ … ≤ x[n-1]
27
Para que estudar
algoritmosde ordenação?
• A maioria das linguagens já implementa algoritmos de
ordenação
39
120.
Para que estudar
algoritmosde ordenação?
• A maioria das linguagens já implementa algoritmos de
ordenação
• Algoritmos de ordenação são bons objetos de estudo:
39
121.
Para que estudar
algoritmosde ordenação?
• A maioria das linguagens já implementa algoritmos de
ordenação
• Algoritmos de ordenação são bons objetos de estudo:
• ordenação é um problema que já foi muito estudado
39
122.
Para que estudar
algoritmosde ordenação?
• A maioria das linguagens já implementa algoritmos de
ordenação
• Algoritmos de ordenação são bons objetos de estudo:
• ordenação é um problema que já foi muito estudado
• os algoritmos apresentam dificuldade média
39
123.
Para que estudar
algoritmosde ordenação?
• A maioria das linguagens já implementa algoritmos de
ordenação
• Algoritmos de ordenação são bons objetos de estudo:
• ordenação é um problema que já foi muito estudado
• os algoritmos apresentam dificuldade média
• eles podem ser usados como base para outros
algoritmos especializados
39
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
imaior = indiceDoMaiorElemento(x, ultimo)
troca(x, imaior, ultimo)
def indiceDoMaiorElemento(x, ultimo):
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
return imaior
12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
Algoritmo
46
ultimo
140.
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
imaior = indiceDoMaiorElemento(x, ultimo)
troca(x, imaior, ultimo)
def indiceDoMaiorElemento(x, ultimo):
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
return imaior
12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
Algoritmo
46
ultimo
141.
Algoritmo
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
47
142.
Algoritmo
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
47
143.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
48
144.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
48
145.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
quantidade de trocas (em qualquer caso): n - 1, que é O(n)
48
146.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
comparações:
(em qualquer caso)
49
147.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
comparações:
(em qualquer caso)
49
148.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
comparações:
(em qualquer caso)
(n-1)
49
149.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
comparações:
(em qualquer caso)
+(n-1) (n-2)
49
150.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
comparações:
(em qualquer caso)
+(n-1) (n-2) + …
49
151.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
comparações:
(em qualquer caso)
+(n-1) (n-2) + +… 2
49
152.
Complexidade
def selectionSort(x):
n =len(x)
for ultimo in seq(n-1, 1, -1):
troca(x, imaior, ultimo)
imaior = 0
for i in seq(1, ultimo):
if x[i] > x[imaior]:
imaior = i
comparações:
(em qualquer caso)
+(n-1) (n-2) + + +… 2 1
49
Intuição
Comparar cada
elemento como próximo
Se estiverem fora da
ordem, troca
http://algoviz.org/OpenDSA/Books/OpenDSA/html/BubbleSort.html56
165.
Intuição
Comparar cada
elemento como próximo
Se estiverem fora da
ordem, troca
Repete várias vezes até
o vetor ficar ordenado
http://algoviz.org/OpenDSA/Books/OpenDSA/html/BubbleSort.html56
Implementação
def bubbleSort(x):
n =len(x)
for penultimo in seq(n-2, 0, -1):
for i in seq(0, penultimo):
if x[i] > x[i + 1]:
troca(x, i, i+1)
12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
57
169.
Complexidade
def bubbleSort(x):
n =len(x)
for penultimo in seq(n-2, 0, -1):
for i in seq(0, penultimo):
if x[i] > x[i + 1]:
troca(x, i, i+1)
58
otimização: flag
170.
Complexidade
def bubbleSort(x):
n =len(x)
for penultimo in seq(n-2, 0, -1):
for i in seq(0, penultimo):
if x[i] > x[i + 1]:
troca(x, i, i+1)
58
otimização: flag
171.
Complexidade
def bubbleSort(x):
n =len(x)
for penultimo in seq(n-2, 0, -1):
for i in seq(0, penultimo):
if x[i] > x[i + 1]:
troca(x, i, i+1)
comparações:
trocas: 0
O(n²)
O(n²)
O(n²)
pior
caso
melhor
caso
58
otimização: flag
172.
Complexidade
def bubbleSort(x):
n =len(x)
for penultimo in seq(n-2, 0, -1):
for i in seq(0, penultimo):
if x[i] > x[i + 1]:
troca(x, i, i+1)
O(n²)
comparações:
trocas: 0
O(n²)
O(n²)
O(n²)
pior
caso
melhor
caso
58
otimização: flag
Algoritmo
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
moveParaPosicaoCerta(x, primeiro)
12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
74
primeiro
200.
Algoritmo
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
moveParaPosicaoCerta(x, primeiro)
def moveParaPosicaoCerta(x, primeiro):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
74
primeiro
201.
Algoritmo
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
moveParaPosicaoCerta(x, primeiro)
def moveParaPosicaoCerta(x, primeiro):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
74
primeiro
202.
Algoritmo
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
def moveParaPosicaoCerta(x, primeiro):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
74
primeiro
203.
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
Algoritmo 12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
75
204.
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
Algoritmo 12 74 42 19 2223
0 1 2 3 4 5
n-6 n-5 n-4 n-3 n-2 n-1
75
205.
Complexidade
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
76
206.
Complexidade
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
76
207.
Complexidade
def insertionSort(x):
n =len(x)
for primeiro in seq(1, n-1):
i = primeiro
while (i >= 1) and (x[i - 1] > x[i]):
troca(x, i - 1, i)
i = i - 1
comparações:
trocas: 0
O(n)
O(n²)
O(n²)
pior
caso
melhor
caso
O(n²)
76
208.
Discussão
E se usarmosbusca binária para encontrar a
posição de inserção de cada elemento?
77
Intuição
• Um vetorcom um elemento está sempre ordenado
• Merge sort: dividir-para-conquistar
85
223.
Intuição
• Um vetorcom um elemento está sempre ordenado
• Merge sort: dividir-para-conquistar
• Dividir vetor no meio sucessivamente
até restarem só sub-vetores de um elemento
85
224.
Intuição
• Um vetorcom um elemento está sempre ordenado
• Merge sort: dividir-para-conquistar
• Dividir vetor no meio sucessivamente
até restarem só sub-vetores de um elemento
• Combinar dois vetores em vetor maior
85
Intuição
Escolhe um elemento(chamaremos de pivô)
Coloca todos os elementos menores que o pivô à
esquerda dele
93
234.
Intuição
Escolhe um elemento(chamaremos de pivô)
Coloca todos os elementos menores que o pivô à
esquerda dele
Coloca todos os elementos maiores que o pivô à
direita dele
93
235.
Intuição
Escolhe um elemento(chamaremos de pivô)
Coloca todos os elementos menores que o pivô à
esquerda dele
Coloca todos os elementos maiores que o pivô à
direita dele
Repete para o sub-vetor à esquerda do pivô
e para o sub-vetor à direita do pivô
93
Algoritmo
• O quicksort não usa memória adicional
• Ver http://algoviz.org/OpenDSA/Books/OpenDSA/
html/Quicksort.html
112
255.
Complexidade
• Melhor caso:se o pivô for sempre a mediana (valor
que divide o vetor em duas partes iguais), a
complexidade será a mesma do merge sort:
O(n log(n))
113
256.
Complexidade
• Melhor caso:se o pivô for sempre a mediana (valor
que divide o vetor em duas partes iguais), a
complexidade será a mesma do merge sort:
O(n log(n))
• Pior caso: se o pivô for sempre o máximo ou o
mínimo, a complexidade será a mesma dos
algoritmos incrementais:
O(n2)
113
257.
Complexidade
• Melhor caso:se o pivô for sempre a mediana (valor
que divide o vetor em duas partes iguais), a
complexidade será a mesma do merge sort:
O(n log(n))
• Pior caso: se o pivô for sempre o máximo ou o
mínimo, a complexidade será a mesma dos
algoritmos incrementais:
O(n2)
• Caso médio: O(n log(n))
113
Discussão
Para vetores muitopequenos, os algoritmos básicos
são mais rápidos do que os avançados
Abordagem híbrida: usar quick sort para dividir
sucessivamente o vetor em sub-vetores. Quando o
sub-vetor for pequeno o suficiente, ordenar com
insertion sort
116
264.
Tópicos Avançados
• Ordenaçãonão-baseada em comparações
• Algoritmos distribuídos
• Ordenação em listas encadeadas
117