Este documento discute o algoritmo de ordenação Shellsort. Primeiramente explica como o Shellsort é uma extensão do algoritmo de ordenação por inserção que permite trocas de elementos mais distantes, melhorando a eficiência. Em seguida detalha a implementação do Shellsort, escolhendo uma sequência de incrementos que garante uma complexidade de no máximo O(N3/2). Por fim, sugere uma abordagem alternativa usando lista encadeada e ordenação por seleção para ordenar grandes conjuntos de dados.
Tutorial aed iii 002 - algoritmo de ordenação shellsort
1. ALGORITMOS E ESTRUTURAS DE DADOS III
Tutorial 2 (usa o compilador de linguagem C Dev-C++ versão 4.9.9.2)
Parte 2 de 3 sobre o algoritmo de ordenação shell (concha) conhecido como Shellsort.
2. 2 O ALGORITMO DE ORDENAÇÃO
1 INTRODUÇÃO
SHELLSORT
Esta série de tutoriais sobre Algoritmos e
Estruturas de Dados III foi escrita usando o O sort por inserção é lento porque troca apenas
Microsoft Windows 7 Ultimate, Microsoft elementos adjacentes. Por exemplo, se o menor
Office 2010, Bloodshed Dev-C++ versão 4.9.9.2 elemento estiver no final do arranjo, são
(pode ser baixado em http://www.bloodshed.net), necessários N passos para colocá-lo em seu
referências na internet e notas de aula do devido lugar. O Shellsort é uma extensão simples
professor quando estudante. Ela cobre desde os do sort por inserção, que ganha velocidade por
algoritmos de ordenação, passando pela pesquisa permitir a troca de elementos distantes entre si.
em memória primária e culminando com a
A ideia é arranjar os dados de tal forma que,
pesquisa em memória secundária.
tomando-se seu h-ésimo elemento (a partir de
Nós entendemos que você já conhece o qualquer posição), tem-se um arranjo ordenado,
compilador Dev-C++. No caso de você ainda não o dito h-ordenado. Falando de outra forma, um
conhecer, dê uma olhada nos tutoriais Dev-C++ arranjo h-ordenado é composto de h arranjos
001 a 017, começando pelo Tutorial Dev-C++ - ordenados, tomados juntos. Através da h-
001 - Introdução. ordenação para valores grandes de h, pode-se
mover elementos dentro do arranjo por grandes
Se não tem problemas com a linguagem C/C++ e distâncias, e assim ordenar mais facilmente para
o compilador Dev-C++, então o próximo passo é valores menores que h. Usando-se este
saber ler, criar e alterar arquivos em disco procedimento para qualquer sequência de valores
usando linguagem C/C++. Se ainda não sabe que termine no tamanho 1 produzirá um arranjo
como fazê-lo, dê uma olhada nos tutoriais Dev- totalmente ordenado.
C++ 001 e 002, começando pelo Tutorial Dev-C++
001 – Criação, Leitura e Alteração de Arquivos. Uma maneira de implementar o Shellsort é, para
cada h, usar o sort de inserção
Se sabe todas as coisas anteriores, então a independentemente em cada um dos h
próxima etapa é conhecer os algoritmos mais subarranjos. A escolha dos valores de h pode ser
básicos de ordenação. Em minhas notas de aula feita pelo critério de Knuth [Niemann 97] 1, como
você encontra um material básico, porém se segue:
detalhado e com algoritmos resolvidos, dos
principais métodos de ordenação existentes. Faça h1 = 1, hs+1 = 3hs +1, e pare com ht quando
ht + 2 ≥ N.
Adotaremos o livro Projeto de Algoritmos com
Implementação em Pascal e C, Editora Cengage Assim, os valores de h são computados como se
Learning, de Nivio Ziviani, como livro-texto da segue:
disciplina. Nele você encontrará os métodos de
h1 = 1
ordenação que iremos estudar.
h2 = (3 * 1) + 1 = 4
Seu próximo passo será estudar os algoritmos de
ordenação por Inserção e por Seleção. Você pode h3 = (3 * 4) + 1 = 13
usar os links anteriores (em inglês) ou fazer uso
do livro-texto. h4 = (3 * 13) + 1 = 40
Em seguida, você precisa conhecer o algoritmo h5 = (3 * 40) + 1 = 121
Shellsort. Para isto, você pode seguir o Tutorial
h6 = (3 * 121) + 1 = 364 etc.
AED 001, desta série, e/ou ler o capítulo
referente no livro-texto. Uma propriedade muito importante [Sedgewick
86]2 é a seguinte:
Se você estiver lendo este tutorial tenha certeza
de ter seguido o Tutorial AED 001. Agora que Shellsort nunca realiza mais do que N3/2
você seguiu todos os passos até aqui, está pronto comparações (para os incrementos 1, 4, 13, ...).
para prosseguir com este tutorial.
1 Niemann, Thomas. Sorting and searching algorithms: a
cookbook. http://www.geocities.com/SoHo/2167/book.html.
2 Sedgewick, Robert. Algorithms. Addison Wesley, 1986.
1
3. Uma implementação para o Shellsort é vista na }
listagem 1 e na listagem 2: vet [j + gap] = value;
}
2.1 FUNCIONAMENTO DO ALGORITMO } while(gap > 1);
}
Acompanhe pela listagem 1. Primeiro ciclo do-
while gera sequência: 1 4 13 40 121 364 1093 Listagem 2:
3280 ... void shellSort(int *vetor, int tamanho)
{
Segundo ciclo for é executado para os valores de
int i = (tamanho - 1) / 2;
h por ordem inversa.
int chave, k, aux;
Operação (vetor com tamanho 100):
Para cada valor de h, 40, 13, 4, 1: while(i != 0)
Utilizar ordenação por inserção para {
criar subvetores ordenados dentro de do
vetor com tamanho 100. {
Vector fica h-ordenado. chave = 1;
for(k = 0; k < MAX - i; ++k)
Para h = 40 existem 40 subvetores
{
ordenados, cada um com 2/3
if(vetor[k] > vetor[k + i])
elementos.
{
Para h = 13 existem 13 subvetores
aux = vetor[k];
ordenados, cada um com 7/8
vetor[k] = vetor[k + i];
elementos.
vetor[k + i] = aux;
...
chave = 0;
Para h = 1 existe 1 (subvetor
}
ordenado, com 100 elementos.
}
} while(chave == 0);
2.2 COMPLEXIDADE i = i / 2;
Complexidade depende da sequência de valores }
utilizada: }
Sequência 1, 4, 13, 40, 121, 364, 1093, ...
2.4 USANDO LISTAS
O(N3/2) comparações
Sequência 1, 8, 23, 77, 281, 1073, 4193, ... Para sequência de dados muito grande, talvez
O(N4/3) comparações seja melhor uma abordagem usando lista e
Sequência 1, 2, 3, 4, 6, 9, 8, 12, 18, 27, 16, ordenação por seleção.
24, ...
O(N(log N)2) comparações Uma sugestão poderia ser:
Interface:
2.3 IMPLEMENTAÇÕES typedef struct node *link;
Listagem 1: struct node {Item item; link next;};
void shellSort(int *vet, int size) { link NEW(Item, link);
int i, j, value; link init(int);
int gap = 1; void show(link);
do { link sort(link);
gap = 3 * gap + 1;
Seleção:
} while(gap < size);
link listselection(link h) {
do {
link max, t, out = NULL;
gap /= 3;
while(h->next != NULL) {
for(i = gap; i < size; i++) {
max = findmax(h);
value = vet[i];
t = max->next; max->next = t->next;
j = i - gap;
t->next = out; out = t;
while(j >= 0 && value < vet[j]) {
}
vet [j + gap] = vet[j];
h->next = out;
j -= gap;
2
4. return(h);
}
A cada passo retira o máximo elemento da lista
atual, e coloca no topo da nova lista.
Exercício de fixação
Implemente um algoritmo usando lista e
ordenação por seleção para ordenar a lista de
10000 inteiros, fornecida no meu blog.
4 TERMINAMOS
Terminamos por aqui. Clique no menu Arquivo,
depois clique na opção Sair.
Corra para o próximo tutorial.
3