A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Vectores (e Listas) : Pesquisa e Ordenação

Apresentações semelhantes


Apresentação em tema: "Vectores (e Listas) : Pesquisa e Ordenação"— Transcrição da apresentação:

1 Vectores (e Listas) : Pesquisa e Ordenação
Pedro Barahona DI/FCT/UNL Introdução aos Computadores e à Programação 2º Semestre 2007/2008 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

2 Leitura para Vectores / Listas de Estruturas
Para ilustrar o conceito de vectores/listas de estruturas (para versões Octave posteriores/anteriores a 3.0), vamos considerar o anterior ficheiro com informação sobre empregados e criar uma lista/vector com essa informação. Nota: Assume-se que no ficheiro (‘empresa_aux.txt’) os campos são separados por tabs horizontais e que os espaços dentro dos nomes já foram substituidos por espaços especiais (non-break spaces). Como anteriormente, a cada linha do ficheiro corresponde uma estrutura, emp, com os campos cod, nome, venc e data. Por exemplo, 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

3 Vectores – Substituição (Octave 3.0 e posteriores)
A leitura dos vários campos de uma estrutura pode ser feita como anteriormente. Um programa, que cria uma vector de estruturas, vec_emps, com a informação sobre os empregados do ficheiro “empresa_aux.txt”, é o seguinte: [f_aux, msg] = fopen("empresa_aux.txt", "r"); n = 0; [emp.cod,emp.nome,emp.venc,emp.data, count] = fscanf(f_aux,"%i%s%f%s","C"); while !feof(f_aux) n = n+1; vec_emps(n) = emp; endwhile; fclose(f_aux); 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

4 Listas – Substituição (versões Octave anteriores a 3.0)
A mesma leitura para uma lista de empregados é indicado abaixo (para versões Octave anteriores a 3.0). O programa cria uma lista, lista_emps, com a informação sobre os empregados do ficheiro “empresa_aux.txt”: [f_aux, msg] = fopen("empresa_aux.txt", "r"); lista_emps = list(); n = 0; [emp.cod,emp.nome,emp.venc,emp.data, count] = fscanf(f_aux,"%i%s%f%s","C"); while !feof(f_aux) n = n+1; lista_emps = append(lista_emps , emp); endwhile; fclose(f_aux); 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

5 Estruturas em Funções (Octave 3.0 e posteriores)
Estruturas (Octave 3.0 e posteriores) podem ser retornadas como resultado de uma função. Por exemplo, a função abaixo retorna a lista anterior e o número dos seus elementos, (se chamada com o ficheiro de nome “empresa_aux.txt”) function [vec_emps, n] = ler_lista_emps(fname); [f_aux, msg] = fopen(fname, "r"); n = 0; [emp.cod,emp.nome,emp.venc,emp.data, count] = fscanf(f_aux,"%i%s%f%s","C"); while !feof(f_aux) n = n+1; vec_emps(n) = emp; endwhile; fclose(f_aux); endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

6 Listas em Funções (versões Octave anteriores a 3.0)
Listas de estruturas (versões Octave anteriores a 3.0) podem também ser retornadas como resultado de uma função. Por exemplo, a função abaixo usa listas em vez dos vectores de estruturas anteriores: function [lista_emps, n] = ler_lista_emps(fname); [f_aux, msg] = fopen(fname, "r"); lista_emps = list(); n = 0; [emp.cod,emp.nome,emp.venc,emp.data, count] = fscanf(f_aux,"%i%s%f%s","C"); while !feof(f_aux) n = n+1; lista_emps = append(lista_emps, emp); endwhile; fclose(f_aux); endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

7 Processamento de Vectores de Estruturas
A partir deste momento, todo o processamento da informação sobre os empregados pode ser feito sem leitura do ficheiro, mas apenas por acesso ao vector vec_emps. Vamos ilustrar esta situação em 3 problemas: Cálculo da média dos vencimentos dos empregados. Selecção dos empregados com o nome Paulo Ordenação dos empregados por ordem crescente de antiguidade 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

8 Cálculo de Médias em Vectores de Estruturas (Octave 3.0 e posteriores)
Uma vez lida a informação dos empregados para o vector vec_emps, ela pode ser acedida directamente e passada como parâmetros de entrada em funções. Assim o cálculo do total e da média dos vencimentos é feito pela chamada da função vencimentos, definida abaixo e chamada com o parâmetro vec_emps. Por exemplo, na instrução [m,t] = vencimentos(vec_emps) function [media, total] = vencimentos(vec_x); total = 0; n = length(vec_x) for i = 1:n total = total + vec_x(i).venc; endfor; media = total / n; % printf("o total de vencimentos é %7.2f \n“, total); % printf(“ e a sua média é %7.2f \n", total/n); endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

9 Cálculo de Médias em Listas (versões Octave anteriores a 3.0)
A função anterior pode ser adaptada para listas de estruturas. Uma vez lida a informação dos empregados para a lista lista_emps, ela pode ser acedida directamente e passada como parâmetros de entrada em funções. Assim o cálculo do total e da média dos vencimentos é feito pela chamada da função vencimentos, definida abaixo e chamada com o parâmetro lista_emps. Por exemplo, na instrução [m,t] = vencimentos(lista_emps) function [media, total] = vencimentos(lista); total = 0; n = length(lista) for i = 1:n total = total + nth(lista,i).venc; endfor; media = total / n; % printf("o total de vencimentos é %7.2f \n“, total); % printf(“ e a sua média é %7.2f \n", total/n); endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

10 Selecção de Elementos em Vectores de Estruturas (Octave 3
Selecção de Elementos em Vectores de Estruturas (Octave 3.0 e posteriores) Igualmente se podem seleccionar os elementos de um vector de estruturas que satisfazem um certo critério. No exemplo abaixo os empregados cujo vencimento é superior a um dado valor são seleccionados e organizados num vector, emps, que é o resultado da função vencimento_maior. Estes empregados podem ser obtidos pela chamada da função emps_mais_de_1000 = vencimento_maior(vec_emps, 1000) function emps = vencimento_maior(vec_x, valor); k = 0; for i = 1:length(lista) if lista(i).venc > valor k = k + 1; emps(k) = lista(i); endif; endfor; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

11 Selecção de Elementos em Listas (Octave 3.0 e posteriores)
O critério utilizado para seleccionar os elementos de um vector de estruturas é arbitrário, podendo ser naturalmente outro. No exemplo abaixo são seleccionados, e retornados como resultado da função emps_com_nome, os empregados que têm uma dada palavra no seu nome. Por exemplo, os empregados cujo nome inclui a palavra “Paulo” são retornados pela chamada da função paulos = emps_com_nome(vec_emps, ‘Paulo’) function emps = emps_com_nome(vec_x, nome); k = 0; for i = 1:length(lista) emp = vec_x(i); if index(toupper(emp.nome),toupper(nome))> 0 k = k + 1; emps(k) = emp; endif; endfor; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

12 Selecção de Elementos em Listas (versões Octave anteriores a 3.0)
As funções anteriores podem ser adaptadas para listas de estruturas: function emps = vencimento_maior(lista, valor); emps = list(); for i = 1:length(lista) emp = nth(lista,i); if emp.venc > valor emps = append(emps, emp); endif; endfor; endfunction; function emps = emps_com_nome(lista, nome); emps = list(); for i = 1:length(lista) emp = nth(lista,i); if index(toupper(emp.nome),toupper(nome))> 0 emps = append(emps, emp); endif; endfor; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

13 Ordenação de Listas e Vectores
As estruturas de dados lineares (nomeadamente listas e vectores) são frequentemente armazenadas de uma forma ordenada. A ordenação facilita, a pesquisa de informação. Como veremos, numa lista ordenada com n elementos a procura de um elemento pode ser feito com log2(n) acessos em vez de n/2 operações (em média). Por exemplo, se uma lista tiver 107 = elementos (por exemplo, o número de portugueses na base de dados do BI), em vez de de acessos à lista (para encontrar um #BI), são necessários apenas cerca de log2(107) ≈ 23.25, em média. Evidentemente a ordenação tem custos. Mas, como é frequentemente o caso, a ordenação é feita 1 vez, e os acessos muitas vezes, compensa manter as estruturas de dados ordenadas. 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

14 Ordenação de Listas e Vectores
Analisemos primeiro a ordenação de vectores (ou listas), para o que existem vários algoritmos (de ordenação) com vantagens e desvantagens em diferentes contextos. Uma característica importante dos algoritmos é o espaço de memória utilizado, que não consideraremos neste caso, já que apenas se utiliza o espaço ocupado pelo vector. Outra característica importante é a sua complexidade, medida em número de acessos ao vector. Este número depende naturalmente do número n de elementos da estrutura de dados utilizada. Embora existam algoritmos (quicksort) mais rápidos (necessitam de cerca de nlog2n acessos), o que apresentamos (bubblesort) é mais simples de descrever (e implementar?). 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

15 Ordenação por Bubble Sort
A ideia do algoritmo é comparar dois elementos consecutivos do vector, e trocá- los se tiverem na ordem “errada”. A comparação é feita entre os n-1 pares do vector, por uma determinada ordem, por exemplo (1,2), (2,3), ..., (n-1,n). No final deste processo, o último elemento já está bem posicionado. Sem qualquer optimização, pode fazer-se outro varrimento, em que ficará bem colocado o penúltimo elemento. Desta forma, e no pior caso, bastará fazer n-1 varrimentos para garantir que o vector ficou ordenado. No total, e para o pior caso, são feitas (n-1)comparações em cada um dos (n-1) varrimentos, em que algumas comparações resultam em trocas. Desta forma serão feitas (n-1)2 comparações, pelo que a complexidade será quadrática no número de elementos do vector, isto é lim (n-1)2  n2 (para valores de n “grandes”). 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

16 Ordenação por Bubble Sort
Podemos observar o comportamento deste algoritmo no (pior) caso abaixo, com um vector de 4 elementos, em ordem decrescente que se pretende ordenar de forma crescente! 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

17 Bubble Sort (Não Optimizado)
A função abaixo implementa o algoritmo de bubble sort com dois ciclos para encadeados. No final destes ciclos o vector está ordenado. function V = bubble_1(V); % bubble sort n = length(V); for k = 1:n-1 % n-1 varrimentos for i = 1:n-1 if V(i) > V(i+1) x=V(i); V(i)=V(i+1); %troca V(i) com V(i+1) V(i+1)=x; endif; endfor; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

18 Optimização do Bubble Sort
O algoritmo pode ser optimizado de duas formas complementares. Diminuição dos ciclos Por um lado, em cada iteração o último valor a ser considerado vai decrescendo de n para n-1, para n-2, .... Desta forma o ciclo interno pode ser parametrizado por um valor k que vai decrescendo em cada ciclo externo. Interrupção dos varrimentos Se um varrimento termina sem trocas, o vector já está ordenado, e não é necessário fazer mais varrimentos. Assim há que identificar numa variável, troca, se houve trocas durante um varrimento. Caso contrário, terminar imediatamente a ordenação. 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

19 Bubble Sort (Optimizado)
As duas optimizações descritas estão implementadas no algoritmo abaixo. Se ao fim de um varrimento não tiver havido trocas, o vector já está ordenado e a função termina sem iniciar mais varrimentos!. function V = bubble_2(V); % bubble sort n = length(V); for k = n-1:-1:1 % k = n-1, n-2, n-3, ... troca = 0; for i = 1:k if V(i) > V(i+1) troca = 1; x=V(i); V(i)=V(i+1); %troca V(i) com V(i+1) V(i+1)=x; endif; endfor; if troca == 0 return endif; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

20 Bubble Sort (Optimizado) (versões Octave 3.0 e posteriores)
Como a unica operação a fazer sobre vectores é trocar dois elementos, o mesmo algoritmo pode servir para ordenar vectores de estruturas. Por exemplo, a função abaixo ordena o vector Vec, por ordem crescente do campo venc. function Lista = bubble_3(Vec); % bubble sort n = length(Vec)-1; for k = n-1:-1:1 troca = FALSE; for i = 1:k if Vec(i).venc > Vec(i+1).venc troca = TRUE; x = Vec(i); %troca V(i) com V(i+1) Vec(i) = Vec(i+1); Vec(i+1) =x; endif; endfor; if !troca then return; endfor:; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

21 Bubble Sort (Optimizado) (versões Octave anteriores a 3.0)
Como a unica operação a fazer sobre vectores é trocar dois elementos, o mesmo algoritmo pode servir para ordenar listas de estruturas. Por exemplo, a função abaixo ordena a lista por ordem crescente do campo venc. function Lista = bubble_3(Lista); % bubble sort n = length(Lista)-1; for k = n-1:-1:1 troca = FALSE; for i = 1:k if nth(lista,i).venc > nth(lista,i+1).venc troca = TRUE; x = nth(Lista,i); %troca V(i) com V(i+1) Lista(i)=nth(Lista,i+1); Lista(i+1)=x; endif; endfor; if !troca then return; endfor:; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

22 Pesquisa Linear em Vectores
Consideremos um vector V, numérico e não ordenado, onde queremos encontrar o número x. O algoritmo abaixo determina se o número x está ou não incluído no vector, comparando x com todos os valores da lista. A função retorna o (primeiro) índice i onde se encontra x (ou seja, V(i) = x), ou retorna 0 se x não estiver incluído no vector A função pode ser facilmente adaptada para uma lista e um campo substituindo-se a comparação para if nth(Lista,i).campo == x function i = procura_linear_1(x,V); for i = 1:length(V); if V(i) == x return; endif endfor; i = 0; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

23 Vectores (e Listas): Pesquisa e Ordenação
Pesquisa em Vectores A complexidade do algoritmo, em termos do número de acessos ao vector, pode ser analisado da seguinte forma: Se x não pertence ao vector, então terão de ser feitas n leituras. Se x pertencer ao vector, o número de leituras é variável. Assumindo que x pode estar em qualquer posição, deverão ser lidos, em média, n/2 valores. Assumindo que x pode estar em V com uma probabilidade p (e, portanto, não estar no vector com uma probabilidade q = 1-p), o número médio de acessos será de aproximadamente p  n/2 + q  n Se p = q = ½ teremos uma complexidade média de ½  ½ n + ½ n = ¾ n o que indica uma complexidade assintótica linear, O(n). 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

24 Pesquisa Linear em Vectores (Optimizada)
A pesquisa pode ser mais rápida se o vector estiver ordenado. Assumindo uma ordenação crescente, a pesquisa pode terminar se o valor V(i) já exceder o valor de x, porque nesse caso, os valores de V(j) com j > i serão ainda maiores! function i = procura_linear_2(x,V); for i = 1:length(V); if V(i) == x return; elseif V(i) > x i = 0; endif endfor; endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

25 Pesquisa Linear em Vectores (Optimizada)
A complexidade, em termos do número de acessos ao vector, pode ser analisado de uma forma semelhante à anterior : Se x pertencer ao vector V, o número de leituras é variável, sendo em média lidos n/2 valores. Se x não pertencer ao vector V, esse facto será descoberto mais cedo ou mais tarde consoante o valor de x (e os valores em V). Em média, podemos assumir igualmente que apenas metade dos valores são testados Como x está em V com uma probabilidade p, e não está com probabilidade 1-p, o número médio de acessos será de p  n/2 + (1-p)  n/2 = n/2 O número de acessos baixa assim de ¾ n para ½ n, mas mantém a mesma complexidade assintótica linear, O(n). 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

26 Vectores (e Listas): Pesquisa e Ordenação
Pesquisa Bipartida Se o vector V estiver ordenado, podemos sempre determinar se x, a existir no vector V, está à frente ou atrás de um elemento testado. Assim, em vez de testar sequencialmente os valores de V, podemos testá-los “em saltos”, delimitando em cada teste a zona do vector onde valerá a pena pesquisar. Esquemáticamente, podemos considerar um esquema de bipartição O algoritmo pode pois considerar um intervalo de pesquisa cada vez menor, como exemplificado de seguida. x > V(i) x < V(i) i 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

27 Vectores (e Listas): Pesquisa e Ordenação
Pesquisa Bipartida Consideremos um vector V, ordenado por ordem crescente, com 31 números, onde queremos encontrar o número x. Inicialmente os índices onde se faz a pesquisa estão no intervalo (1,31). Podemos comparar x com o número intermédio entre 1 e 31 = 16 = (1+31)/2). Se V(16) = x, este está encontrado. Se V(16) < x, este deverá ser procurado no intervalo (17,31). Se V(16) > x, este deverá ser procurado no intervalo (1,15). Neste último caso, podemos comparar x com o número intermédio 8 = (1+15)/2 Se V(8) = x, este está encontrado. Se V(8) < x, este deverá ser procurado no intervalo (9,15). Se V(8) > x, este deverá ser procurado no intervalo (1,7). 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

28 Vectores (e Listas): Pesquisa e Ordenação
Pesquisa Bipartida No segundo caso, podemos comparar x com o número intermédio 12 = 9+15/2. Se V(12) = x, este está encontrado. Se V(12) < x, este deverá ser procurado no intervalo (13,15). Se V(12) > x, este deverá ser procurado no intervalo (9,11). No segundo caso, podemos comparar x com o número intermédio 14 = (13+15)/2. Se V(14) = x, este está encontrado. Se V(14) < x, este deverá ser procurado no intervalo (15,15). Se V(14) > x, este deverá ser procurado no intervalo (13,13). Nestes últimos casos, são feitas comparações com um só elemento, V(13) ou V(15), que garantem a verificação sobre se x está ou não no vector V . 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

29 Vectores (e Listas): Pesquisa e Ordenação
Pesquisa Bipartida No máximo, são feitas 5 comparações, com V(16), V(8), V(12), V(14) e V(15), o que confirma que o número máximo de acessos é da ordem de log2(n), já que log2(31) = 4.95 ≈ 5. Em geral, o intervalo inicial, de largura n, é reduzido para metade em cada um de p passos, sendo feita uma comparação em cada passo, e terminando o processo quando o intervalo tiver largura 1. Assim, temos n  ½  ½  ...  ½ = 1, donde n / 2p = 1 e portanto n = 2p ou p = log2(n). Como p é o número de comparações, a pesquisa bipartida tem, como visto atrás, complexidade assintótica logaritmica O( log2(n)). Assim para vectores (ou listas) com 109 valores, uma pesquisa requer em média log2(109) ≈ 29.9, e não 500*106 acessos. Se cada acesso demorar 1 ms, a pesquisa bipartida demora cerac de 30 ms, em comparação com 500 seg = 10 min! 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação

30 k = procura_bipartida(x,V,1,length(V)).
Pesquisa Bipartida Dadas as vantagens, vale a pena utilizar a pesquisa bipartida. Eis uma possível implementação, recursiva, em que se pretende determinar se o número x está no vector V, entre as posições i e j. Naturalmente, a função será chamada como k = procura_bipartida(x,V,1,length(V)). function k = procura_bipartida(x,V,i,j); if i > j k = % x não pertence a V else m = round((i+j)/2) if V(m) == x k = m; return; elseif V(m) < x i = m+1; % o j mantem-se else j = m-1; % o i mantem-se endif; k = procura_bipartida(x,V,i,j); endif endfunction; 21 Maio 2008 Vectores (e Listas): Pesquisa e Ordenação


Carregar ppt "Vectores (e Listas) : Pesquisa e Ordenação"

Apresentações semelhantes


Anúncios Google