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 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
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
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

Tutorial aed iii 002 - algoritmo de ordenação shellsort

  • 1.
    ALGORITMOS E ESTRUTURASDE 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 ALGORITMODE 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 parao 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