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

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

11 de Maio de 2006Listas e Ordenação1 Pedro Barahona DI/FCT/UNL Introdução aos Computadores e à Programação 2º Semestre 2005/2006.

Apresentações semelhantes


Apresentação em tema: "11 de Maio de 2006Listas e Ordenação1 Pedro Barahona DI/FCT/UNL Introdução aos Computadores e à Programação 2º Semestre 2005/2006."— Transcrição da apresentação:

1 11 de Maio de 2006Listas e Ordenação1 Pedro Barahona DI/FCT/UNL Introdução aos Computadores e à Programação 2º Semestre 2005/2006

2 11 de Maio de 2006 Listas e Ordenação 2 Listas Uma lista é uma sequência de dados do mesmo tipo, simples ou complexo, para as quais estão definidas (em Octave) as operações de: Criação: list(elem_1, elem_2,..., elem_k) –Cria uma lista, com os elementos de 1 a k (ou uma lista vazia se k = 0) Adição: append(nome_lista,elem_1,...,elem_k) –Acrescenta os os elementos de 1 a k à lista com o nome indicado no 1º argumento Acesso: nth(nome_lista, k) –Acede ao k-ésimo elemento da lista. De notar que esse elemento pode ser uma estrutura arbitrariamente complexa.

3 11 de Maio de 2006 Listas e Ordenação 3 Listas Para ilustrar o conceito de lista, vamos considerar um ficheiro com informação sobre empregados e criar uma lista com essa informação. A cada linha do ficheiro corresponde uma estrutura, emp, com os campos cod, nome, venc e data. Por exemplo, A leitura dos vários campos de uma estrutura pode ser feita como anteriormente [emp.cod,emp.nome,emp.venc,emp.data,count] = fscanf(f_aux,"%i%s%f%s","C");

4 11 de Maio de 2006 Listas e Ordenação 4 Leitura de Listas O programa completo, que cria uma lista, tab_empregados, com a informação sobre os empregados do ficheiro empresa_aux.txt, é o seguinte: [f_aux, msg] = fopen("empresa_aux.txt", "r"); tab_empregados = 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; tab_empregados = append(tab_empregados, emp); [emp.cod,emp.nome,emp.venc,emp.data, count] = fscanf(f_aux,"%i%s%f%s","C"); endwhile; fclose(f_aux);

5 11 de Maio de 2006 Listas e Ordenação 5 Estruturas e Listas em Funções Estruturas e listas 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: function [tabela, n] = ler_tab_emp(ficheiro); rem_sp(ficheiro,empresa_aux.txt) [f_aux, msg] = fopen(empresa_aux.txt, "r"); tabela = 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; tabela = append(tabela, emp); [emp.cod,emp.nome,emp.venc,emp.data, count] = fscanf(f_aux,"%i%s%f%s","C"); endwhile; fclose(f_aux); endfunction;

6 11 de Maio de 2006 Listas e Ordenação 6 Processamento de Listas A partir deste momento, todo o processamento da informação sobre os empregados pode ser feito sem leitura do ficheiro, mas apenas por acesso à lista tab_empregados. 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

7 11 de Maio de 2006 Listas e Ordenação 7 Média de Vencimentos Uma vez lida a informação dos empregados para a lista tab_empregados, com n elementos, ela pode ser acedida directamente, sem necessidade de nova leitura do ficheiro. O cálculo do total e da média dos vencimentos é feito através de um ciclo que percorre todas as estruturas da lista e soma os correspondentes campos venc. %[tab_empregados, n] = ler_tab_emp(empresa_in_var.txt); total = 0; for i = 1:n total = total + nth(tab_empregados,i).venc; endfor; printf("o total de vencimentos é %7.2f \n, total); printf( e a sua média é %7.2f \n", total/n);

8 11 de Maio de 2006 Listas e Ordenação 8 Selecção de Elementos de Listas Igualmente se podem seleccionar os elementos de uma lista que satisfazem um certo critério. No exemplo abaixo são seleccionados, e mostrados ao terminal, os empregados cujo vencimento é superior a 1000 %[tab_empregados,n] = ler_tab_emp(empresa_in_var.txt); printf("Lista de empregados com mais de 1000 : \n"); for i = 1:n emp = nth(tab_empregados,i); if emp.venc > 1000 printf( %-30s\t%7.2f\n",emp.nome,emp.venc); endif; endfor;

9 11 de Maio de 2006 Listas e Ordenação 9 Selecção de Elementos de Listas O critério utilizado para seleccionar os elementos de uma lista é arbitrário, podendo ser naturalmente outro. No exemplo abaixo são seleccionados, e mostrados ao terminal, os empregados que têm o nome Paulo (bem como o seu vencimento) %[tab_empregados, n] = ler_tabela(empregados_var.txt); for i = 1:n emp = nth(tab_empregados,i); if index(toupper(emp.nome),"PAULO") > 0 printf("\t%-30s\t%7.2f\t\n",emp.nome,emp.venc); endif; endfor;

10 11 de Maio de 2006 Listas e Ordenação 10 Ordenação de Vectores, Matrizes e Listas As estruturas de dados (vectores, matrizes ou listas) 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 log 2 (n) acessos em vez de n operações. Por exemplo, se uma lista tiver 10 7 = 10 000 000 elementos (por exemplo, o número de portugueses na base de dados do BI), em vez de 10 000 000 de acessos à lista (para encontrar um #BI), são necessários apenas cerca de log 2 (10 7 ) 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.

11 11 de Maio de 2006 Listas e Ordenação 11 Ordenação de 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 log 2 n acessos), o que apresentamos (bubblesort) é mais simples de descrever.

12 11 de Maio de 2006 Listas e Ordenação 12 Ordenação de Vectores – Bubble Sort A ideia do algoritmo é comparar dois elementos consecutivos do vector, e trocá-los se tiverem na ordem errada. Esta comparação é feita entre todos os n-1 pares do vector, por uma determinada ordem, por exemplo (1,2), (2,3),..., (n-1,n). Se não fôr feita nenhuma troca, o vector já está ordenado. Caso contrário, repete-se o processo. No pior caso (em que V(n) era o elemento mais pequeno do vector), é necessário executar n-1 vezes este varrimento do vector (mais 1 vez para ter a certeza). No total, e para o pior caso, são feitas n (n-1) comparações, das quais algumas serão trocas, pelo que a complexidade será quadrática no número de elementos do vector ( n 2 ).

13 11 de Maio de 2006 Listas e Ordenação 13 Ordenação de Vectores – Bubble Sort Podemos observar o comportamento deste algoritmo nos dois casos abaixo com um vector com 4 elementos, que se pretende ordenar de forma crescente. Pior caso 4*3 = 12 comparações 6 trocas Caso típico 3*3 = 9 comparações 3 trocas

14 11 de Maio de 2006 Listas e Ordenação 14 Ordenação de Vectores – Bubble Sort A função abaixo implementa o algoritmo de bubble sort. No início de cada ciclo for a variável troca é falsa. Se se mantiver falsa no fim do ciclo, o vector já se encontra ordenado e não é necessário mais nenhum ciclo for. function V = bubble_vec(V); % bubble sort n = length(V) do troca = false; for i = 1:n-1 if V(i) > V(i+1) troca = true; x=V(i); V(i)=V(i+1); V(i+1)=x; %troca endif; endfor; until ! troca; endfunction;

15 11 de Maio de 2006 Listas e Ordenação 15 Ordenação de Listas – Bubble Sort A função abaixo implementa o algoritmo de bubble sort mas para uma lista de estruturas, ordenada por um campo (venc). function L = bubble_list(L); % bubble sort n = length(L); do troca = false; for i = 1:n-1 reg1 = nth(L,i); reg2 = nth(L,i+1); if reg1.venc < reg2.venc troca = true; L(i) = reg2; L(i+1) = reg1; endif; endfor; until ! troca; endfunction; Nota: o campo não pode ser passado como parâmetro. Porquê?

16 11 de Maio de 2006 Listas e Ordenação 16 Pesquisa em Vectores Consideremos um vector V, 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 índice i onde se encontra x (ou seja, V(i) = x), ou retorna 0 se x não estiver incluído no vector function i = procura_vec(x,V); for i = 1:length(V); if V(i) == x return; endif endfor; i = 0; endfunction;

17 11 de Maio de 2006 Listas e Ordenação 17 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 não estar 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).

18 11 de Maio de 2006 Listas e Ordenação 18 Pesquisa Linear em Vectores Ordenados A complexidade da pesquisa pode ser melhorada se o vector está 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_vec_lin(x,V); i = 1; while i V(i); i = i + 1; endwhile if x != V(i) i = 0 endif; endfunction;

19 11 de Maio de 2006 Listas e Ordenação 19 Pesquisa Linear em Vectores Ordenados A complexidade, em termos do número de acessos ao vector, pode ser analisado da seguinte forma: –Como anteriormente, se x pertencer ao vector, o número de leituras é variável, sendo em média lidos n/2 valores. –Se x não pertencer ao vector, esse facto poderá ser descoberto no início ou no fim, consoante o valor de x. Em média, podemos assumir 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).

20 11 de Maio de 2006 Listas e Ordenação 20 Pesquisa Bipartida em Vectores Ordenados Se o vector está ordenado, podemos sempre determinar se x, a existir no vector 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 11 de Maio de 2006 Listas e Ordenação 21 Pesquisa Bipartida em Vectores Ordenados 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 16 (i.e. (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 (i.e. (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).

22 11 de Maio de 2006 Listas e Ordenação 22 Pesquisa Bipartida em Vectores Ordenados No segundo caso, podemos comparar x com o número intermédio 12 (i.e. (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 (i.e. (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 indicam se x está ou não no vector V.

23 11 de Maio de 2006 Listas e Ordenação 23 Pesquisa Bipartida em Vectores Ordenados 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 log 2 (n), já que log 2 (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 / 2 p = 1 e portanto n = 2 p ou p = log 2 (n). Como p é o número de comparações, a pesquisa bipartida tem, como visto atrás, complexidade assintótica logaritmica O( log 2 (n))

24 11 de Maio de 2006 Listas e Ordenação 24 Pesquisa Bipartida em Vectores Ordenados O algoritmo descrito pode ser implementado através das funções procura_vec_bip e p_vec_bip, que retornam o índice do elemento do vector V onde se encontra o valor x, caso ele exista. Caso contrário retornam o valor 0. A função procura_vec_bip apenas conta os elementos do vector e chama a função p_vec_bip, que procura o elemento x no vector V nos elementos com índices entre dois limites, inferior e superior (no início estes limites são 1 e n, respectivamente): function i = procura_vec_bip(x,V); n = length(V); i = p_vec_bip(x,V,1,n); endfunction.

25 11 de Maio de 2006 Listas e Ordenação 25 Pesquisa Bipartida em Vectores Ordenados A função p_vec_bip verifica se x é o elemento do meio do vector. Se não, procura nos índices ou inferiores ou superiores, consoante x for menor ou maior que esse elemento. A pesquisa para quando os limites superior e inferior forem os mesmos, testando-se se x é o valor desse elemento. function i = p_vec_bip(x,V,lo,up); i = 0; while up >= lo & i == 0 mid = floor((lo+up)/2); if x > V(mid) lo = mid+1; elseif x < V(mid) up = mid-1 else i = mid; endif endwhile endfunction

26 11 de Maio de 2006 Listas e Ordenação 26 Pesquisa Bipartida em Listas Ordenadas As funções pesquisa_list e p_list, abaixo apresentadas, são as correspondentes funções de acesso a uma lista L, ordenada por um determinado campo (no exemplo, cod). function i = procura_lista_bip(x,L); i = p_lista_bip(x,L,1,length(L)); endfunction. function i = p_lista_bip(x,L,lo,up); i = 0; while up >= lo & i == 0 mid = floor((lo+up)/2); if x > V(mid).cod lo = mid+1; elseif x < V(mid).cod up = mid-1 else i = mid; endif endwhile endfunction


Carregar ppt "11 de Maio de 2006Listas e Ordenação1 Pedro Barahona DI/FCT/UNL Introdução aos Computadores e à Programação 2º Semestre 2005/2006."

Apresentações semelhantes


Anúncios Google