DOCUMENTAO ORDENAO DE LISTAS DUPLAMENTE ENCADEADAS Discentes: LUCAS IZUMI DE OLIVEIRA ALBERES DO ESPRITO SANTO Diamantina 2011 UNIVERSIDADE FEDERAL DOS VALES DO JEQUITINHONHA E MUCURI SISTEMAS DE INFORMAO Introduo Este programa tem por objetivo variados mtodos de ordenao lista duplamente encadeada dentro da estrutura e outro para seu antecessor, alm dos campos responsveis pelo armazenamento das informaes corresponde ao mtodo de rearranjar um conjunto de objetos em uma ordem crescente ou decrescente. O programa trabalha com os mtodos: Quicksort. Utilizando a biblioteca execuo de cada uma das funes, para tamanho pequeno (N =10) a eficcia de cada um dos mtodos. Ao ser executado o programa comea o processo de ordenao e clculo de tempo. Cada funo chamada A interface do programa apresenta a lista e seus elementos (apenas para N=10), que gerada aleatoriamente pe indicado o mtodo de ordenao a ser utilizado, a lista ordenada pelo mtodo referido e o tempo de execuo. Este programa tem por objetivo implementar e calcular o tempo de operao de variados mtodos de ordenao em listas duplamente encadeadas. lista duplamente encadeada cada elemento tem um ponteiro para o prximo dentro da estrutura e outro para seu antecessor, alm dos campos responsveis pelo armazenamento das informaes (Figura 1). A ordenao corresponde ao mtodo de rearranjar um conjunto de objetos em uma ordem crescente ou decrescente. Figura 1 O programa trabalha com os mtodos: Insertion Sort, Selection Sort e Quicksort. Utilizando a biblioteca timer.h, calculado o tempo gasto na execuo de cada uma das funes, para listas duplamente encadeadas tamanho pequeno (N =10) e mdio (N =500). Desta forma possvel verificar a eficcia de cada um dos mtodos. Ao ser executado o programa comea o processo de ordenao e clculo de tempo. Cada funo chamada e a cada operao o tempo gasto calculado A interface do programa apresenta a lista e seus elementos (apenas para N=10), que gerada aleatoriamente pela funo enche_lista(). J unto da lista indicado o mtodo de ordenao a ser utilizado, a lista ordenada pelo mtodo referido e o tempo de execuo. calcular o tempo de operao de . Em uma m um ponteiro para o prximo dentro da estrutura e outro para seu antecessor, alm dos campos A ordenao corresponde ao mtodo de rearranjar um conjunto de objetos em uma ordem Insertion Sort, Selection Sort e , calculado o tempo gasto na listas duplamente encadeadas de . Desta forma possvel verificar Ao ser executado o programa comea o processo de ordenao e clculo de calculado. A interface do programa apresenta a lista e seus elementos (apenas para . J unto da lista indicado o mtodo de ordenao a ser utilizado, a lista ordenada pelo mtodo Implementao Este programa foi implementado utilizando a linguagem de programao C++. O projeto conta com trs (3) arquivos de cabealho (.h) e dois arquivos fonte (.cpp). O cabealho lista_de.h possui as definies de classes, funes de lista e as funes de ordenao. Inicialmente construda uma classe Nodo e uma definio de tipo hNodo (correspondente a Nodo*). Dentro da estrutura da classe definida a varivel valor (inteiro) e os links dir e esq. Os links so responsveis por apontar para os elementos da direita e esquerda do n. A prxima classe construda a Lista. Dentro dela so definidas as funes que: adicionam um elemento a uma lista (insere_elemento), removem um elemento de uma lista (remove_elemento), retira o menor elemento de uma lista (retira_menor), verifica se a lista est vazia (vazia), insere um elemento no fim da lista (insere_fim), insere um elemento no comeo da lista (insere_inicio), imprime os elementos da lista (print) e as funes relativas aos mtodos de ordenao. A funo insere_elemento() recebe como parmetro o valor do elemento a ser inserido e a posio, ambos em nmeros inteiros. Primeiro verifica-se se a lista est vazia e, caso esteja, o elemento inserido e os ponteiros primeiro e ltimo so direcionados a ele. Em seguida verifica-se se o elemento deve ser adicionado no comeo ou fim. A ltima verificao se o elemento deve ser inserido no meio da lista. Um lao for percorre a lista at chegar na posio indicada. Durante a execuo do lao um ponteiro auxiliar caminha pela lista at a posio indicada, onde o elemento adicionado. As funes insere_fim() e insere_inicio() usam como base a funo insere_elemento(). Elas recebem por parmetro um inteiro, que o elemento a ser adicionado, e chamam a funo de insero, cada uma j com a posio definida: 0 para a incio e nmero de elementos para a fim. A funo remove_elemento() funciona de forma semelhante de insero. Ela pode retirar um elemento do inicio, fim ou meio da lista A funo retira_menor() uma funo do tipo hNodo que percorre a lista em busca do menor elemento e o retorna, removendo-o da lista ao mesmo tempo com a funo remove_elemento. Atravs de um lao for, todos os elementos so comparados e a posio dos menores armazenada. Quando todos a lista j foi percorrida obtem-se a posio exata do menor elemento A funo vazia() simplesmente verifica o nmero de elementos de uma lista, se este for igual a zero (0), significa que a lista est vazia, caso contrrio, no. O nmero de elementos definido por uma varivel inteira, declarada dentro da estrutura da Lista. Para a construo dos mtodos de ordenao, foi necessrio o uso de funes auxiliares gmeas a algumas funes anteriores para tratamento das listas auxiliares. As funes insere_aux, aux_back e aux_front possuem as mesmas caractersticas da insere_elemento, insere_fim e insere_inicio, respectivamente. A funo de ordenao ordena_selecao() retira o menor elemento da lista principal e adiciona no fim de uma lista auxiliar. O processo repetido at que a lista principal esteja vazia. Como os elementos esto sendo adicionados lista auxiliar em ordem, ela j estar ordenada ao final. Nesta funo criado um n auxiliar (aux). Verifica-se ento se a lista principal est vazia, se estiver quer dizer que todos os elementos j esto na lista auxiliar, logo, os ponteiros primeiro e ultimo, referentes ao primeiro e ultimo elemento da lista principal, respectivamente, passam a apontar para o primeiro e ultimo elemento da lista auxiliar. O nmero de elementos da lista principal (agora 0) passa a valer o mesmo que o nmero de elementos da lista auxiliar, voltando ao seu valor original. Se a lista no estiver vazia, a funo retira o menor elemento com a ajuda da funo retira_menor e insere no fim da lista auxiliar, esta operao se repete at que a lista principal fique vazia. A funo de ordenao ordena_insercao() vai retirando o primeiro elemento da lista principal e adicionando, j de forma ordenada, lista auxiliar. So declarados trs (3) elementos: um contador inteiro (cont) e dois ns auxiliares, p e aux. Como na funo ordena_selecao, verifica-se, primeiramente, se a lista principal est vazia. Se estiver, quer dizer que todos os elementos j esto na lista auxiliar, logo, os ponteiros primeiro e ultimo, referentes ao primeiro e ultimo elemento da lista principal, respectivamente, passam a apontar para o primeiro e ultimo elemento da lista auxiliar. O nmero de elementos da lista principal (agora 0) passa a valer o mesmo que o nmero de elementos da lista auxiliar, voltando ao seu valor original. Se o programa passar por essa verificao, ou seja, a lista no est vazia, obtido o valor do primeiro elemento da lista e armazenado no n auxiliar. Este elemento ento apagado da lista principal. Em seguida, h outra verificao de lista vazia, mas agora sobre a lista auxiliar. Se ela estiver vazia, ento o elemento pode ser adicionado em qualquer lugar, caso contrrio, verifica-se se o novo elemento a ser adicionado menor que o primeiro elemento da lista auxiliar, se isto for verdadeiro, ele adicionado no comeo da lista. Se o elemento for maior que o primeiro, o programa percorre toda a lista procurando por algum lugar para este elemento, atravs de um lao do-while. O lao se repete enquanto no encontrar um nmero menor que o elemento a ser adicionado. A cada loop verificado se o prximo elemento da lista existe (ou seja, no nulo). Se ele no for, o ponteiro auxiliar passa anda para frente e o contador acrescido em um (1). Ao final do lao obtem-se a posio exata onde o novo elemento deve ser encaixado, que o valor da varivel contador (cont). O elemento adicionado na lista auxliar atravs da funo insere_aux, passados como parmetro o seu valor e a varivel de contador. Este processo se repete at que a lista principal esteja vazia. A funo ordena_quick() responsvel apenas por fazer a chamada da funo quicksort(). Na funo quicksort so criados ponteiros auxiliares que so usados posteriormente pela funo partio(). Tambm criado um novo n chamado de piv. Este n armazenar o elemento piv do mtodo quicksort. A funo quicksort() verifica primeiramente se a lista principal possui mais de um elemento, se possuir, ela define o piv chamando a funo de partio e em seguida chama ela prpria, recursivamente, em cima dos ponteiros auxiliares que foram anteriormente declarados. Aps as chamadas recursivas as listas separadas so juntadas, onde verifica-se se os ponteiros auxiliares so nulos ou no e faz os ponteiros principais apontarem para o comeo da primeira lista separada e o final da segunda. Quando a funo verifica que a lista principal possui apenas um (1) elemento, ela encerrada, as recurses empilhadas resolvem e a juno acima mencionada realizada. A funo partio() retorna um hNodo e responsvel por definir o piv e separar as listas recursivamente. Esta funo define como piv o ultimo elemento da lista principal. Em seguida, atravs de um lao while que se repete at que no tenha mais nenhum elemento na lista, um elemento removido, comparado com o piv e adicionado em uma das listas. Se o elemento comparado for menor que o piv, ele adicionado na lista da esquerda, caso contrrio, adicionado na lista da direita. Ao final a funo retorna o elemento piv. A biblioteca timer.h simplesmente aponta o arquivo que deve ser utilizado de acordo com o sistema operacional da mquina. Se este for Windows, ser utilizado o PerfTimer.h, se for Linux, o Timer_linux.h. PerfTimer.h e PerfTimer.cpp so os arquivos responsveis pelo funcionamento da contagem de tempo. O arquivo principal do projeto d_enc.cpp declara as listas, chama as funes de ordenao e faz o clculo de tempo, alm de criar uma interface com informaes para o usurio. Grfico O grfico abaixo apresenta os resultados obtidos no clculo de tempo de ordenao de listas duplamente encadeadas. Para questes de comparao, foram adicionados ao grfico dados relativos ao tempo de ordenao gasto em vetores pelos mesmos mtodos utilizados. Estudo de Complexidade Casos Insertion Selection Quicksort Pior O(n^2) O(n^2) O(n^2) Mdio O(n^2) O(n^2) O(nlog n) Melhor O(n) O(n^2) O(nlog n) O programa principal no conta com estrutura de repetio alguma, apenas faz a chamada de funes relacionadas com a lista, portanto possui complexidade O(n). Concluso A ordenao de listas possui aspectos interessantes quando comparada com vetores. O fato das listas serem mais flexveis torna o funcionamento de determinadas funes de ordenao mais simples de se executar. Um bom exemplo o Insertion Sort, que precisaria mover elementos pelo vetor. Na lista, precisamos simplesmente indicar onde os ponteiros devem apontar, salvando um precioso espao na memria. Outras funes, porm, acabam se tornando um pouco mais complicadas de se implementar, de maneira lgica. Como se trabalha basicamente com ponteiros que apontam uns para os outros, preciso tomar um certo cuidado no seu manuseio para evitar acessos no-permitidos na memria. Bibliografia Stack Overflow. Disponvel em <http://stackoverflow.com/>Acesso em: 27 de Novembro de 2011. Buscas em Listas. Disponvel em < http://www.eecis.udel.edu/~portnoi/classroom/estrutura_dados/2007_1/lecture_ slides/aula04.pdf>Acesso em: 3 de Dezembro de 2011.