Algoritmos de Ordenação Aplicação a Listas de Registos Jorge Cruz DI/FCT/UNL Programação para as Ciências Experimentais 1º Semestre 2005/2006 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 1 Ordenação de Registos • Um problema importante é o da apresentação dos registos de acordo com uma determinada ordem. Por exemplo: – Apresentar uma listagem dos empregados por ordem alfabética; – Apresentar uma listagem dos empregados ordenados por antiguidade; • Complementarmente, podem-se adicionar restrições: – Apresentar uma listagem, ordenada por ordem alfabética, dos empregados que tenham um vencimento superior a 1000 €; – Apresentar uma listagem, ordenada por antiguidade, dos empregados que tenham um vencimento superior a 1000 €; • Em qualquer dos casos é importante saber ordenar os registos de acordo com um determinado critério. • Vamos então descrever dois algoritmos simples de ordenação (insert sort e bubble sort) e depois mostrar como podem ser aplicados na ordenação de registos (guardados em listas). 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 2 Algoritmos de Ordenação: insert sort • Suponhamos que queríamos ordenar o seguinte vector: v0 = [12, 2, 9, 15, 10] • Talvez a maneira mais intuitiva de o fazer seja através do algoritmo insert sort: – Começa-se por criar um vector v1 apenas com o primeiro elemento de v0: • v1 = [12] – Acrescentam-se o restantes elementos, um a um, de modo a manter v1 sempre ordenado: • • • • v1 = [2, 12] v1 = [2, 9, 12] v1 = [2, 9, 12, 15] v1 = [2, 9, 10, 12, 15] • O problema fundamental deste algoritmo é como é que se faz para inserir um elemento numa lista ordenada. 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 3 Algoritmos de Ordenação: insert sort • Para inserir um elemento numa lista ordenada podemos percorrer a lista do fim para o principio até se descobrir a posição que o elemento deve ocupar na ordenação. • Ao percorrer a lista podemos ir chegando uma posição à direita todos os elementos maiores do que o novo elemento de modo a arranjar espaço para ele: function L = insert(L0,x) L=L0; n=length(L); for i=n:-1:1 if (L(i)<x) L(i+1)=x; return; else L(i+1)=L(i); if (i==1) L(i)=x; return; endif endif endfor endfunction 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 4 Algoritmos de Ordenação: insert sort • A seguinte função insert_sort começa por criar um vector inicial apenas com o primeiro elemento da lista para ordenar e vai acrescentando todos os outros elementos, um a um, recorrendo à função insert: function L = insert_sort(L0) n=length(L0); L=[L0(1)]; for i=2:n L=insert(L,L0(i)); endfor endfunction 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 5 Algoritmos de Ordenação: bubble sort • Um outro algoritmo de ordenação, um pouco mais sofisticado, é o bubble sort. – Suponhamos que queremos ordenar o vector: • v0 = [12, 2, 9, 15, 10] – Começa-se por percorrer o vector inicial (até ao penúltimo elemento) e trocar dois elementos sempre estiverem na ordem errada: • v1 = [2, 12, 9, 15, 10] [2, 9, 12, 15, 10] [2, 9, 12, 15, 10] [2, 9, 12, 10, 15] – Agora, que garantidamente o último elemento do vector é o maior, repete-se o processo (para os elementos ainda não garantidamente ordenados) : • 25 Novembro 2005 v1 = [2, 9, 12, 10, 15] [2, 9, 12, 10, 15] [2, 9, 10, 12, 15] • v1 = [2, 9, 10, 12, 15] • v1 = [2, 9, 10, 12, 1 [2, 9, 10, 12, 15] Algoritmos de Ordenação Aplicação a Listas de Registos 6 Algoritmos de Ordenação: bubble sort • O código Octave do algoritmo de ordenação bubble sort será então: function L = bubble_sort(L0) n=length(L0); L=L0; for k=n-1:-1:1 for i=1:k if L(i+1)<L(i) temp=L(i); L(i)=L(i+1); L(i+1)=temp; endif; endfor; endfor; endfunction 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 7 Algoritmos de Ordenação e Listas • Os algoritmos de ordenação como o bubble sort e o insert sort podem ser utilizados para ordenar uma lista de registos se considerarmos vectores de índices. • Por exemplo: – o vector [1, 2, 3, 4, 5] pode representar os cinco primeiros elementos de uma lista na sequência: 1º, 2º, 3º, 4º e 5º. – o vector [5, 4, 3, 2, 1] pode representar os mesmos cinco elementos mas por ordem inversa. • Se t é uma lista de registos, nth(t,i) é o elemento de índice i • No exemplo da lista de empregados, o código, nome, vencimento e data do empregado de índice i são respectivamente: – – – – nth(t,i).cod nth(t,i).nome nth(t,i).venc nth(t,i).data 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 8 Algoritmos de Ordenação e Listas • Deste modo, a função listagem_nome_venc apresenta o nome e vencimento dos empregados de acordo com a ordenação dos índices representada no vector L: function listagem_nome_venc(t,L) n=length(L); for i=1:n printf("Nome: %-25s Vencimento: %7.2f \n“ ,nth(t,L(i)).nome, nth(t,L(i)).venc); endfor; endfunction • Assim, para obtermos uma listagem ordenada basta ordenar os índices e chamar a função listagem_nome_venc. 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 9 Algoritmos de Ordenação e Listas • Para ordenar os índices pode-se usar um algoritmo de ordenação tendo o cuidado de “redefinir” a comparação entre dois elementos de acordo com o critério de ordenação que se pretende. • Por exemplo, a função bubble_sort_list_cod usa o bubble sort para ordenar os índices existentes no vector L0 por ordem crescente do código do empregado: 25 Novembro 2005 function L = bubble_sort_list_cod(t,L0) L=L0; n=length(L0); for k=n-1:-1:1 for i=1:k if nth(t,L(i+1)).cod < nth(t,L(i)).cod temp=L(i); L(i)=L(i+1); L(i+1)=temp; endif; endfor; endfor; endfunction Algoritmos de Ordenação Aplicação a Listas de Registos 10 Algoritmos de Ordenação e Listas • Para ordenar os índices pode-se usar um algoritmo de ordenação tendo o cuidado de “redefinir” a comparação entre dois elementos de acordo com o critério de ordenação que se pretende. • A função bubble_sort_list_venc é idêntica à anterior mas ordena os índices existentes no vector L0 por ordem crescente do vencimento do empregado: 25 Novembro 2005 function L = bubble_sort_list_venc(t,L0) L=L0; n=length(L0); for k=n-1:-1:1 for i=1:k if nth(t,L(i+1)).venc < nth(t,L(i)).venc temp=L(i); L(i)=L(i+1); L(i+1)=temp; endif; endfor; endfor; endfunction Algoritmos de Ordenação Aplicação a Listas de Registos 11 Algoritmos de Ordenação e Listas • Para ordenar os índices pode-se usar um algoritmo de ordenação tendo o cuidado de “redefinir” a comparação entre dois elementos de acordo com o critério de ordenação que se pretende. • A função bubble_sort_list_data ordena os índices existentes no vector L0 por ordem crescente de antiguidade do empregado, e usa a função anterior para comparar duas datas: 25 Novembro 2005 function L = bubble_sort_list_data(t,L0) L=L0; n=length(L0); for k=n-1:-1:1 for i=1:k if anterior(nth(t,L(i+1)).data,nth(t,L(i)).data)==1 temp=L(i); L(i)=L(i+1); L(i+1)=temp; endif; endfor; endfor; endfunction Algoritmos de Ordenação Aplicação a Listas de Registos 12 Algoritmos de Ordenação e Listas • Para ordenar os índices pode-se usar um algoritmo de ordenação tendo o cuidado de “redefinir” a comparação entre dois elementos de acordo com o critério de ordenação que se pretende. • A função bubble_sort_list_nome ordena os índices existentes no vector L0 por ordem alfabética dos nomes dos empregados, e usa a função my_str_norm_before para comparar dois nomes: function L = bubble_sort_list_nome(t,L0) L=L0; n=length(L0); for k=n-1:-1:1 for i=1:k if my_str_norm_before (nth(t,L(i+1)).nome,nth(t,L(i)).nome)==1 temp=L(i); L(i)=L(i+1); L(i+1)=temp; endif; endfor; endfor; endfunction 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 13 Algoritmos de Ordenação e Listas • Se além da ordenação estivermos também interessados em seleccionar apenas alguns registos, podemos previamente construir um vector apenas com os índices dos registos seleccionados. • Por exemplo, a função select_venc cria um vector apenas com os índices de L0 cujos empregados tenham um vencimento superior a 1000 €: function L = select_venc(t,L0) L=[]; j=0; n=length(L0); for i = 1:n if nth(t,L0(i)).venc > 1000 j=j+1; L(j)=L0(i); endif; endfor; endfunction • Assim para obter apenas estes índices ordenados pelo nome do empregado bastaria: L=select_venc(t,L0); L=bubble_sort_list_nome(t,L) 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 14 Algoritmos de Ordenação e Listas • Podemos agora dar resposta a cada uma das perguntas anteriores. • Primeiro lê-se o ficheiro de texto para uma tabela: [t,n] = ler_tabela("empresa_aux_var.txt"); • Para apresentar uma listagem dos empregados por ordem alfabética de nomes ou por antiguidade, teríamos que considerar todos os índices, ordená-los de acordo com o critério e apresentar os campos que queremos visualizar dos respectivos registos: L=[1:n]; L1=bubble_sort_list_nome(t,L);listagem_nome_venc(t,L1); L2=bubble_sort_list_data(t,L);listagem_nome_venc(t,L2); • Se além disto estivermos apenas interessados nos empregados com um salário superior a 1000 €, temos que previamente seleccionar apenas os índices dos registos que satisfazem o critério: L=[1:n]; L=select_venc(t,L); L1=bubble_sort_list_nome(t,L);listagem_nome_venc(t,L1); L2=bubble_sort_list_data(t,L);listagem_nome_venc(t,L2); 25 Novembro 2005 Algoritmos de Ordenação Aplicação a Listas de Registos 15