4
respostas

[Sugestão]

Fazendo os testes de mesa da função quickSort, notei que a verificação do tamanho do array não faz muito sentido ("if (array.length > 1)" na linha 5 do código desenvolvido na aula). No decorrer da execução do código, o array nunca é de fato dividido (apenas os pontos de início e fim do trecho analisado são modificados, mas o array em si permanece sempre com a mesma quantidade de elementos). Ou seja, em todas as camadas de recursividade essa linha vai sempre ler o mesmo valor para 'array.length' Dessa forma, não é necessário verificar o tamanho do array, já que o que encerra a recursividade da execução é o "encontro" entre os pontos inicial e final de análise em cada "camada" de execução. Mesmo executando o código (já sem a verificação de length) com um array de apenas um elemento, ele roda e se encerra normalmente, já que os pontos de início e final de análise coincidem logo de partida.

4 respostas

Oi Vinícius, tudo bem?

Realmente, durante a execução do código, o array não é dividido, apenas os pontos de início e fim do trecho analisado são modificados.

No entanto, a verificação do tamanho do array é necessária para garantir que a recursão seja encerrada corretamente. Quando o array possui apenas um elemento, não é necessário fazer a divisão, pois ele já está ordenado. Então, o "if (array.length > 1)" é utilizado para verificar se o array possui mais de um elemento e, assim, continuar com a recursão.

Um exemplo: se tivermos um array com 10 elementos, a função quick sort será chamada várias vezes até que cada subarray tenha apenas um elemento. Em seguida, esses subarrays serão mesclados e ordenados.

No caso de um array com apenas um elemento, a recursão é encerrada e o array é considerado ordenado. Mesmo que o código seja executado com um array de apenas um elemento, ele roda e se encerra normalmente, pois o ponto de início e fim de análise coincidem logo de partida.

Um abraço e bons estudos.

Oi, Lorena! Tudo bem, sim! E com você? Muito obrigado pela resposta!

Eu ainda não consegui entender a necessidade da verificação feita por esse if. Vou tentar detalhar a minha compreensão do funcionamento da função para ficar mais fácil você apontar a falha na minha interpretação.

Usando o exemplo da aula, a função quickSort() é chamada inicialmente com o argumento listaLivros, um array de 11 elementos. Ao passar por esse primeiro if, o retorno será true (11 > 1). Daí será chamada a função particiona() que, após fazer as devidas verificações e manipular os valores de 'esquerda' e 'direita', fará algumas alterações na ordenação do array original (porém sem alterar seu tamanho) através de trocaLugar() e retornará um valor para a variável indiceAtual.

O próximo passo é passar pelo if (esquerda < indiceAtual - 1). Essa verificação sendo true, a função quickSort é chamada novamente, e o array passado como argumento nessa segunda execução segue sendo listaLivros, que segue tendo 11 elementos e passará novamente pelo primeiro if de quickSort como (11 > 1).

E isso continua ocorrendo em todas as camadas de recursão. Embora listaLivros tenha sua ordem alterada ao longo do processamento das diversas recursões, seu length não é alterado em momento nenhum. Em todas as camadas de execução do quickSort, 'if (array.length > 1)' sempre será (11 > 1). Por isso eu não vejo como essa verificação é responsável por interromper as recursões.

Nos testes de mesa que eu fiz, cada camada de execução de quickSort foi encerra quando: os argumentos 'esquerda' e 'direita' entram na função com 1 unidade de diferença (ex.: esquerda = 3 e direita = 4) e então o retorno da função particiona() para indiceAtual é igual ao valor de 'direita' (4, nesse exemplo). Nesse caso:

  • if (esquerda < indiceAtual -1) será (3 < 4 -1) => (3 < 3) => false
  • if (indiceAtual < direita) será (4 < 4) => false

Passando por ambos if's como falso, essa camada de execução de quickSort é encerrada, retornando ao ponto de execução da camada anterior, que seguirá executando e possivelmente entrando em novas camadas, e será encerrada quando a mesma condição ocorrer (ou seja, 'esquerda' for igual a 'direita -1' e particiona() retornar um valor igual a 'direita'; digamos esquerda = 6, direita = 7, e particiona() retornando 7). E assim sucessivamente para cada camada.

Eu testei a função sem a verificação 'if (array.length > 1', para diversos tamanhos de lista (incluindo uma lista com 1 elemento), e tudo funcionou dentro do esperado.

Oii Vinícius,

A função quickSort é um algoritmo de ordenação que utiliza a estratégia de dividir para conquistar. Ela funciona da seguinte maneira: o array original é dividido em subarrays menores com base em um pivô (um elemento do array) e, em seguida, esses subarrays são ordenados. O processo de divisão e ordenação é repetido recursivamente até que o array esteja completamente ordenado.

O bloco "if (array.length > 1)" desempenha um papel fundamental nesse algoritmo, e sua principal função é determinar quando a recursão deve ser encerrada. Vamos entender o motivo por trás desse bloco de código.

  1. Base da Recursão: Quando você executa o quickSort em um array com apenas um elemento, esse array é considerado automaticamente como ordenado. Portanto, não há necessidade de dividir um array com apenas um elemento em subarrays menores. O algoritmo pode simplesmente retornar o array, economizando tempo e recursos.

    Veja o exemplo:

    const array = [7];
    const sortedArray = quickSort(array);
    // Neste caso, o array já está ordenado, e a recursão é encerrada.
    
  2. Divisão do Array: O bloco "if (array.length > 1)" é fundamental quando o array possui mais de um elemento. Ele determina se o array deve ser dividido em subarrays menores. Se o array tiver apenas um elemento ou nenhum, a divisão não é necessária, pois já está ordenado.

    Veja o exemplo:

    const array = [7, 3, 9, 1];
    const sortedArray = quickSort(array);
    // Neste caso, o array será dividido em subarrays menores para ordenação.
    
  3. Evitando Recursão Infinita: Sem o bloco "if (array.length > 1)", a função quickSort continuaria a chamar a si mesma indefinidamente, pois não haveria uma condição de parada. Isso resultaria em uma recursão infinita, consumindo recursos da máquina e levando a um erro de estouro de pilha.

  4. Controle da Recursão: A condição "if (array.length > 1)" garante que a recursão ocorra apenas quando há pelo menos dois elementos no array. Isso garante que o algoritmo seja aplicado somente a arrays que podem ser divididos em subarrays menores. Quando a recursão alcança um ponto em que os subarrays possuem apenas um elemento, a recursão é encerrada automaticamente, pois a condição não é mais satisfeita.

Portanto, a verificação do tamanho do array desempenha um papel importante na lógica do quickSort, garantindo que a recursão funcione corretamente, mesmo quando o array já está ordenado ou possui apenas um elemento. Sem essa verificação, a recursão seria desnecessariamente mais complexa e poderia levar a problemas de desempenho e estouro de pilha em casos com arrays de tamanho considerável.

Espero que esta explicação tenha esclarecido a importância desse bloco de código na função quickSort.

Um abraço e bons estudos.

Oi, Lorena!

Novamente, muito obrigado pelo retorno!

Eu ainda não consegui enxergar em que momento o algoritmo divide a array original em arrays menores, justificando a linha "if (array.length > 1)" =/

Eu subi meu código no github e incluí lá também um arquivo Excel em que fiz meu teste de mesa para "dissecar" a execução do código passo a passo. Se você puder dar uma olhada (principalmente na planilha), eu fico muito grato. Eu sinto que entendi o funcionamento do código, mas pelas suas explicações aparentemente eu estou perdendo algum ponto e acho importante entender onde está essa divergência.

Obs: na planilha eu considerei a execução com uma lista simples de números, não uma lista de objetos, para simplificar a escrita e acompanhamento do passo a passo. Mas entendo que esse detalhe não altera a lógica de funcionamento do código (pelo menos não nesse ponto da subdivisão da array original).

Obs2: no arquivo Excel, além do teste de mesa do quickSort, também tem outra planilha com o teste de mesa do mergeSort. Nesse segundo caso, eu compreendi que ocorre a subdivisão das arrays através do método slice(). No caso do quickSort eu não consigo identificar qual método ou manipulação da array original altera sua length.

Obs3: eu incluí também no repositório uma versão do quickSort sem esse primeiro bloco if para você testar, caso ache necessário. Eu executei esse código no terminal usando a lista de objetos passada na aula (inclusive incluindo e retirando elementos) e tudo correu normalmente.