<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Cayo Dias - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Cayo Dias - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 30 May 2026 19:37:05 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/author/cayo/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Algoritmos de ordenação explicados com exemplos em Python, Java e C++ ]]>
                </title>
                <description>
                    <![CDATA[ O que é um algoritmo de ordenação? Os algoritmos de ordenação são um conjunto de instruções que recebem um array ou lista como entrada e organizam os itens em uma ordem específica. As ordenações mais comumente realizadas são a numérica ou a alfabética (também chamada de lexicográfica) e podem ser ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/algoritmos-de-ordenacao-explicados-com-exemplos-em-python-java-e-c/</link>
                <guid isPermaLink="false">623f38596a6ca90519ad030b</guid>
                
                    <category>
                        <![CDATA[ Algoritmos ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Cayo Dias ]]>
                </dc:creator>
                <pubDate>Sun, 15 May 2022 20:47:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/05/5f9c9ede740569d1a4ca3f9d-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/sorting-algorithms-explained-with-examples-in-python-java-and-c/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Sorting Algorithms Explained with Examples in JavaScript, Python, Java, and C++</a>
      </p><h2 id="o-que-um-algoritmo-de-ordena-o">O que é um algoritmo de ordenação?</h2><p>Os algoritmos de ordenação são um conjunto de instruções que recebem um array ou lista como entrada e organizam os itens em uma ordem específica.</p><p>As ordenações mais comumente realizadas são a numérica ou a alfabética (também chamada de lexicográfica) e podem ser em ordem crescente (A-Z, 0-9) ou decrescente (Z-A, 9-0).</p><h2 id="por-que-algoritmos-de-ordena-o-s-o-importantes">Por que algoritmos de ordenação são importantes?</h2><p>Os algoritmos de ordenação são importantes em Ciência da Computação porque a ordenação pode, muitas vezes, reduzir a complexidade de um problema. Esses algoritmos têm aplicações diretas em algoritmos de busca, algoritmos de banco de dados, métodos de divisão e conquista, algoritmos de estrutura de dados e muito mais.</p><h3 id="vantagens-e-desvantagens-dos-algoritmos">Vantagens e desvantagens dos algoritmos</h3><p>Ao usar algoritmos diferentes, algumas perguntas devem ser feitas. Qual o tamanho da coleção que está sendo ordenada? Quanta memória está disponível para uso? A coleção precisa crescer?</p><p>As respostas a essas perguntas podem determinar qual algoritmo funcionará melhor para a situação. Alguns algoritmos como a ordenação por intercalação (<em>merge sort</em>, em inglês) podem precisar de muito espaço para serem executados, enquanto a ordenação por inserção nem sempre é a mais rápida, mas não requer muitos recursos para isso.</p><p>Você deve determinar quais são os requisitos do sistema e suas limitações antes de decidir qual algoritmo usar.</p><h2 id="algoritmos-de-ordena-o-comuns">Algoritmos de ordenação comuns</h2><p>Alguns dos algoritmos de ordenação mais comuns são:</p><ul><li>Selection Sort (ordenação por seleção)</li><li>Bubble Sort</li><li>Insertion Sort (ordenação por inserção)</li><li>Merge Sort (ordenação por intercalação)</li><li>Quick Sort (ordenação rápida)</li><li>Heap Sort</li><li>Counting Sort</li><li>Radix Sort</li><li>Bucket Sort</li></ul><p>Antes de detalharmos cada um deles, contudo, vamos aprender um pouco mais sobre como são classificados os algoritmos de ordenação.</p><h3 id="classifica-o-de-um-algoritmo-de-ordena-o">Classificação de um algoritmo de ordenação</h3><p>Os algoritmos de ordenação podem ser categorizados com base nos seguintes parâmetros:</p><ol><li><strong>Baseado no número de trocas ou inversões necessários:</strong> Este é o número de vezes que o algoritmo troca os elementos para ordenar uma entrada. A ordenação por seleção requer o número mínimo de trocas.</li><li><strong>Baseado no número de comparações:</strong> Este é o número de vezes que o algoritmo compara elementos para ordenar uma entrada. Usando a <a href="https://www.freecodecamp.org/portuguese/news/notacao-big-o-explicada-com-exemplos/">notação Big-O</a>, os exemplos de algoritmos de ordenação listados acima requerem, pelo menos, <code>O(nlogn)</code> comparações no melhor caso e <code>O(n^2)</code> comparações no pior caso para a maioria das saídas.</li><li><strong>Baseado no uso ou não de recursão:</strong> Alguns algoritmos, tal como <code>Quick Sort</code> (ordenação rápida), usa técnicas recursivas para ordenar uma entrada. Outros algoritmos de ordenação, como &nbsp;<code>Selection Sort</code> (ordenação por seleção) ou &nbsp;<code>Insertion Sort</code> (ordenação por inserção), usam técnicas não recursivas. Por fim, alguns algoritmos de ordenação, como &nbsp;<code>Merge Sort</code> (ordenação por intercalação), usam tanto técnicas recursivas como não recursivas para ordenar uma entrada.</li><li><strong>Baseado na estabilidade:</strong> Algoritmos de ordenação são considerados &nbsp;<code>estáveis</code> se o algoritmo mantiver a ordem relativa dos elementos com chaves iguais. Em outras palavras, dois elementos equivalentes permanecem, após a ordenação, na mesma ordem em que estavam antes da ordenação.<br>Imagine, por exemplo, que tenhamos um array de entrada <code>[1, 2, 3, 2, 4]</code>. Para ajudar na diferenciação entre os valores que são iguais – neste caso, os <code>2</code> – usaremos <code>2a</code> e <code>2b</code>, tornando o array &nbsp;<code>[1, 2a, 3, 2b, 4]</code>.<br>Algoritmos de ordenação estáveis manterão a ordem de <code>2a</code> e <code>2b</code>. Ou seja, teremos o algoritmo ordenado <code>[1, 2a, 2b, 3, 4]</code>. Já os instáveis, por sua vez, não mantêm a ordem dos valores iguais, resultando em <code>[1, 2b, 2a, 3, 4]</code>. <code>Insertion sort</code> , &nbsp;<code>Merge Sort</code> &nbsp;e &nbsp;<code>Bubble Sort</code> são estáveis, enquanto <code>Heap Sort</code> &nbsp;e <code>Quick Sort</code> não são.</li><li><strong>Baseado na necessidade de espaço adicional:</strong> Alguns algoritmos podem ordenar uma lista sem criar outra inteiramente nova. Chamamos um algoritmo assim de algoritmo de ordenação &nbsp;<code>in loco</code> e ele requer um espaço adicional <code>O(1)</code> constante para a ordenação. Quando os algoritmos não são <code>in loco</code>, &nbsp;uma outra lista é criada durante a ordenação.<br><code>Insertion sort</code> &nbsp;e &nbsp;<code>Quick sort</code> realizam a ordenação <code>in loco</code>, já que os elementos são movidos em torno de um ponto fixo e não utilizam um array à parte durante o processo de ordenação. <br>No <code>Merge sort</code>, por outro lado, o tamanho da entrada deve ser alocado de antemão para armazenar a saída durante o processo de ordenação. Isso exige um espaço adicional na memória para o processo de ordenação.</li></ol><h2 id="bucket-sort">Bucket Sort</h2><p>Bucket Sort é um algoritmo de ordenação por comparação que opera em elementos dividindo-os em diferentes buckets (segmentos menores de mesmo tamanho) e, em seguida, ordenando esses buckets individualmente. Cada bucket é ordenado individualmente usando um algoritmo de ordenação separado ou aplicando o algoritmo de bucket sort recursivamente.</p><p>Bucket Sort é útil principalmente quando a entrada é distribuída uniformemente em um intervalo. Por exemplo, suponhamos que tenhamos recebido um array grande de números de ponto flutuante uniformemente distribuídos entre os limites inferior e superior e precisamos ordená-lo.</p><p>Uma maneira simples de se resolver esse problema seria usar um algoritmo de ordenação, como o Merge sort, o Heap Sort ou o Quick Sort. No entanto, esses algoritmos garantem uma complexidade de tempo de, no melhor caso, <code>O(NlogN)</code>. Usando o bucket sort, contudo, a tarefa acima pode ser concluída em tempo <code>O(N)</code>.</p><h3 id="pseudoc-digo-para-bucket-sort-">Pseudocódigo para Bucket Sort:</h3><pre><code>void bucketSort(float[] a,int n)

{

    for(each floating integer 'x' in a)

    {
        insert x into bucket[n*x]; 
    }

    for(each bucket)

    {
        sort(bucket);
    }

}
</code></pre><h2 id="counting-sort">Counting Sort</h2><p>Counting Sort é uma técnica de ordenação baseada em chaves compreendidas em um intervalo específico. Ela funciona contando o número de objetos com valores de chave distintos (tipo de hash). Em seguida, fazendo alguma operação para calcular a posição de cada objeto na sequência de saída.</p><h3 id="exemplo-">Exemplo:</h3><pre><code>Para simplificar, considere os dados no intervalo de 0 a 9. 
Dados de entrada: 1, 4, 1, 2, 7, 5, 2
  1) Use um array para armazenar a contagem de cada objeto único.
  Índice:       0  1  2  3  4  5  6  7  8  9
  Contagem:     0  2  2  0  1  1  0  1  0  0

  2) Modifique o array de contagem de modo que cada elemento em cada índice armazene a soma das contagens anteriores. 
  Índice:       0  1  2  3  4  5  6  7  8  9
  Contagem:     0  2  4  4  5  6  6  7  7  7

O array de contagem modificado indica a posição que cada objeto ocupará no array de saída.
 
  3) Posicione cada objeto do array de entrada no array de saída de modo que sua posição final seja igual ao seu valor de contagem menos 1.
  Processe os dados de entrada: 1, 4, 1, 2, 7, 5, 2. A contagem do valor (no array de contagem) é 2.
  Assim, coloque o valor 1 no índice 1 (2 - 1) do array de saída. Subtraia 1 do valor de contagem aramazenado no índice 1 do array de contagem, de modo que o próximo valor do array de entrada seja colocado em uma posição, no array de saída, igual a esse valor menos 1.
  
</code></pre><h3 id="propriedades">Propriedades</h3><ul><li>Complexidade espacial: <code>O(K)</code> </li><li>Desempenho no melhor caso: <code>O(n+K)</code></li><li>Desempenho médio: <code>O(n+K)</code></li><li>Desempenho no pior caso: <code>O(n+K)</code></li><li>Estável: Sim (<code>K</code> é o número de elementos distintos no array)</li></ul><h3 id="implementa-o-em-javascript">Implementação em JavaScript</h3><pre><code class="language-js">let numbers = [1, 4, 1, 2, 7, 5, 2];
let count = [];
let i, z = 0;
let max = Math.max(...numbers);      
// inicializar o contador
for (i = 0; i &lt;= max; i++) {
    count[i] = 0;
}
for (i=0; i &lt; numbers.length; i++) {
    count[numbers[i]]++;
}
for (i = 0; i &lt;= max; i++) {
    while (count[i]-- &gt; 0) {
        numbers[z++] = i;
    }
}
// dar como resultado o array ordenado
for (i=0; i &lt; numbers.length; i++) {
    console.log(numbers[i]);
}
</code></pre><h3 id="implementa-o-em-c-">Implementação em C++</h3><pre><code class="language-cpp">#include &lt;iostream&gt;

void countSort(int upperBound, int lowerBound, std::vector&lt;int&gt; numbersToSort) //limites superior e inferior dos números no vetor
{
  int range = upperBound - lowerBound;                  //cria um intervalo grande o suficiente para obter todos os números entre o mínimo e o máximo
  std::vector&lt;int&gt; counts (range);                      //inicializa contagens do tamanho do intervalo
  std::fill(counts.begin(), counts.end(), 0);           //preenche os vetores com zeros
  
  for (int i = 0; i &lt; numbersToSort.size(); i++)
  {
      int index = numbersToSort[i] - lowerBound; //Por exemplo, se 5 for o limite inferior e numberToSort[i] for 5. index será 0 e o       counts[index]+= 1;                         //contagem de 5 será armazenada em counts[0]
  }
  
  std::cout &lt;&lt; counts &lt;&lt; std::endl;
} 
</code></pre><h3 id="implementa-o-em-swift">Implementação em Swift</h3><pre><code class="language-swift">func countingSort(_ array: [Int]) {
  // Cria um array para armazenar a contagem de cada elemento
  let maxElement = array.max() ?? 0
  var countArray = [Int](repeating: 0, count: Int(maxElement + 1))
  
  for element in array {
    countArray[element] += 1
  }
  var z = 0
  var sortedArray = [Int](repeating: 0, count: array.count)

  for index in 1 ..&lt; countArray.count {
    //exibe o elemento de índice o número de vezes necessárias
    while countArray[index] &gt; 0 {
      sortedArray[z] = index
      z += 1
      countArray[index] -= 1
    }
  }
  
  print(sortedArray)
}
</code></pre><h2 id="insertion-sort-ordena-o-por-inser-o-">Insertion Sort (ordenação por inserção)</h2><p>Insertion sort é um algoritmo de ordenação simples para um pequeno número de elementos.</p><h3 id="exemplo--1">Exemplo:</h3><p>Em insertion sort, você compara o elemento &nbsp;<code>chave</code> &nbsp;com os elementos anteriores. Se os elementos anteriores são maiores do que o elemento <code>chave</code>, então você move o elemento anterior para a próxima posição.</p><p>Comece do índice 1 até o tamanho do array de entrada.</p><p>[ 8 3 5 1 4 2 ]</p><p>Passo 1 :</p><pre><code>      chave = 3 //começando no índice 1.

      Aqui a `chave` será comparada com os elementos anteriores.

      Neste caso, `chave` é comparada com 8. Como 8 &gt; 3, movemos o elemento 8 para a próxima posição e inserimos a `chave` na posição anterior.

      Resultado: [ 3 8 5 1 4 2 ]
</code></pre><p>Passo 2 :</p><figure class="kg-card kg-image-card"><img src="https://github.com/blulion/freecodecamp-resource/blob/master/insertion_sort/2.png?raw=true" class="kg-image" alt="[ 3 8 5 1 4 2 ]" width="600" height="400" loading="lazy"></figure><pre><code>      chave = 5 //índice 2

      8 &gt; 5 //movemos o 8 para o índice 2 e inserimos o 5 no índice 1.

      Resultado: [ 3 5 8 1 4 2 ]
</code></pre><p>Passo 3 :</p><figure class="kg-card kg-image-card"><img src="https://github.com/blulion/freecodecamp-resource/blob/master/insertion_sort/3.png?raw=true" class="kg-image" alt="[ 3 5 8 1 4 2 ]" width="600" height="400" loading="lazy"></figure><pre><code>      chave = 1 //índice 3

      8 &gt; 1     =&gt; [ 3 5 1 8 4 2 ]  

      5 &gt; 1     =&gt; [ 3 1 5 8 4 2 ]

      3 &gt; 1     =&gt; [ 1 3 5 8 4 2 ]

      Resultado: [ 1 3 5 8 4 2 ]
</code></pre><p>Passo 4 :</p><figure class="kg-card kg-image-card"><img src="https://github.com/blulion/freecodecamp-resource/blob/master/insertion_sort/4.png?raw=true" class="kg-image" alt="[ 1 3 5 8 4 2 ]" width="600" height="400" loading="lazy"></figure><pre><code>      chave = 4 //índice 4

      8 &gt; 4   =&gt; [ 1 3 5 4 8 2 ]

      5 &gt; 4   =&gt; [ 1 3 4 5 8 2 ]

      3 &gt; 4   ≠&gt;  pare

      Resultado: [ 1 3 4 5 8 2 ]
</code></pre><p>Passo 5 :</p><figure class="kg-card kg-image-card"><img src="https://github.com/blulion/freecodecamp-resource/blob/master/insertion_sort/5.png?raw=true" class="kg-image" alt="[ 1 3 4 5 8 2 ]" width="600" height="400" loading="lazy"></figure><pre><code>      chave = 2 //índice 5

      8 &gt; 2   =&gt; [ 1 3 4 5 2 8 ]

      5 &gt; 2   =&gt; [ 1 3 4 2 5 8 ]

      4 &gt; 2   =&gt; [ 1 3 2 4 5 8 ]

      3 &gt; 2   =&gt; [ 1 2 3 4 5 8 ]

      1 &gt; 2   ≠&gt; pare

      Resultado: [1 2 3 4 5 8]
</code></pre><figure class="kg-card kg-image-card"><img src="https://github.com/blulion/freecodecamp-resource/blob/master/insertion_sort/6.png?raw=true" class="kg-image" alt="[ 1 2 3 4 5 8 ]" width="600" height="400" loading="lazy"></figure><p>O algoritmo mostrado abaixo é uma versão ligeiramente otimizada para evitar trocar o elemento <code>chave</code> em cada iteração. Aqui, o elemento &nbsp;<code>chave</code> &nbsp;será trocado ao final da iteração (step).</p><pre><code>    InsertionSort(arr[])
      for j = 1 to arr.length
         key = arr[j]
         i = j - 1
         while i &gt;= 0 and arr[i] &gt; key
            arr[i+1] = arr[i]
            i = i - 1
         arr[i+1] = key
		</code></pre><p>Aqui está uma implementação detalhada em JavaScript:</p><pre><code class="language-js">function insertion_sort(A) {
    var len = array_length(A);
    var i = 1;
    while (i &lt; len) {
        var x = A[i];
        var j = i - 1;
        while (j &gt;= 0 &amp;&amp; A[j] &gt; x) {
            A[j + 1] = A[j];
            j = j - 1;
        }
        A[j+1] = x;
        i = i + 1;
    }
}
</code></pre><p>Uma implementação rápida em Swift é mostrada abaixo:</p><pre><code class="language-swift">  var array = [8, 3, 5, 1, 4, 2]

  func insertionSort(array:inout Array&lt;Int&gt;) -&gt; Array&lt;Int&gt;{
      for j in 0..&lt;array.count {
          let key = array[j]
          var i = j-1

          while (i &gt; 0 &amp;&amp; array[i] &gt; key){
              array[i+1] = array[i]
              i = i-1
          }
          array[i+1] = key
      }
      return array
  }
</code></pre><p>O exemplo Java é mostrado abaixo:</p><pre><code class="language-java">public int[] insertionSort(int[] arr) {
      for (int j = 1; j &lt; arr.length; j++) {
         int key = arr[j];
         int i = j - 1;
         while (i &gt;= 0 &amp;&amp; arr[i] &gt; key) {
            arr[i+1] = arr[i];
            i -= 1;
         }
         arr[i+1] = key;
      }
      return arr;
}</code></pre><p>E em &nbsp;c....</p><pre><code class="language-c">void insertionSort(int arr[], int n) 
{ 
   int i, key, j; 
   for (i = 1; i &lt; n; i++) 
   { 
       key = arr[i]; 
       j = i-1;
       while (j &gt;= 0 &amp;&amp; arr[j] &gt; key) 
       { 
           arr[j+1] = arr[j]; 
           j = j-1; 
       } 
       arr[j+1] = key; 
   } 
} 
</code></pre><h3 id="propriedades-">Propriedades:</h3><ul><li>Complexidade espacial: O(1)</li><li>Complexidade temporal: O(n), O(n* n), O(n* n) para o melhor, médio e pior caso, respectivamente.</li><li>Melhor caso: o array já está ordenado</li><li>Caso médio: o array está ordenado aleatoriamente</li><li>Pior caso: o array está ordenado em ordem inversa.</li><li>Ordenação in loco: Sim</li><li>Estável: Sim</li></ul><h2 id="heapsort">Heapsort</h2><p>Heapsort é um algoritmo de ordenação eficiente baseado no uso de estruturas de dados denominadas heaps (máxima/mínima). Um heap é uma estrutura de dados baseada em árvore que satisfaz a propriedade heap – ou seja, para um heap máximo, a chave de qualquer nó é menor ou igual à chave de seu pai (se tiver um pai).</p><p>Essa propriedade pode ser aproveitada para acessar o elemento máximo no heap em tempo O(logn) usando o método maxHeapify. Realizamos esta operação n vezes, cada vez movendo o elemento máximo no heap para o topo do heap e extraindo-o do heap para um array ordenado. Assim, após n iterações teremos uma versão ordenada do array de entrada.</p><p>O algoritmo exige que uma estrutura de dados heap seja construída primeiro. O algoritmo não é estável, o que significa que ao comparar objetos com a mesma chave, a ordenação original não será preservada.</p><p>Este algoritmo é executado em tempo O(nlogn) e requer espaço adicional O(1) [O(n) incluindo o espaço necessário para armazenar os dados de entrada], uma vez que todas as operações são executadas inteiramente in loco.</p><p>A complexidade de tempo melhor, pior e média do Heapsort é O(nlogn). Embora heapsort tenha uma complexidade de pior caso melhor do que o quicksort, quando bem implementado, o quicksort é executado mais rapidamente na prática. Heapsort é um algoritmo baseado em comparação, portanto, pode ser usado para conjuntos de dados não numéricos, na medida em que alguma relação (propriedade de heap) possa ser definida sobre os elementos.</p><p>Uma implementação em Java é apresentada abaixo :</p><pre><code class="language-java">import java.util.Arrays;
public class Heapsort {

	public static void main(String[] args) {
		//array de teste
		Integer[] arr = {1, 4, 3, 2, 64, 3, 2, 4, 5, 5, 2, 12, 14, 5, 3, 0, -1};
		String[] strarr = {"hope you find this helpful!", "wef", "rg", "q2rq2r", "avs", "erhijer0g", "ewofij", "gwe", "q", "random"};
		arr = heapsort(arr);
		strarr = heapsort(strarr);
		System.out.println(Arrays.toString(arr));
		System.out.println(Arrays.toString(strarr));
	}
	
	//O(nlogn) TEMPO, O(1) ESPAÇO, NÃO ESTÁVEL
	public static &lt;E extends Comparable&lt;E&gt;&gt; E[] heapsort(E[] arr){
		int heaplength = arr.length;
		for(int i = arr.length/2; i&gt;0;i--){
			arr = maxheapify(arr, i, heaplength);
		}
		
		for(int i=arr.length-1;i&gt;=0;i--){
			E max = arr[0];
			arr[0] = arr[i];
			arr[i] = max;
			heaplength--;
			arr = maxheapify(arr, 1, heaplength);
		}
		
		return arr;
	}
	
	//Cria maxheap a partir de um array
	public static &lt;E extends Comparable&lt;E&gt;&gt; E[] maxheapify(E[] arr, Integer node, Integer heaplength){
		Integer left = node*2;
		Integer right = node*2+1;
		Integer largest = node;
		
		if(left.compareTo(heaplength) &lt;=0 &amp;&amp; arr[left-1].compareTo(arr[node-1]) &gt;= 0){
			largest = left;
		}
		if(right.compareTo(heaplength) &lt;= 0 &amp;&amp; arr[right-1].compareTo(arr[largest-1]) &gt;= 0){
			largest = right;
		}	
		if(largest != node){
			E temp = arr[node-1];
			arr[node-1] = arr[largest-1];
			arr[largest-1] = temp;
			maxheapify(arr, largest, heaplength);
		}
		return arr;
	}
}
</code></pre><p>Implementação em C++</p><pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;
void heapify(int arr[], int n, int i) 
{ 
    int largest = i; 
    int l = 2*i + 1;  
    int r = 2*i + 2;
    if (l &lt; n &amp;&amp; arr[l] &gt; arr[largest]) 
        largest = l;
    if (r &lt; n &amp;&amp; arr[r] &gt; arr[largest]) 
        largest = r;
    if (largest != i) 
    { 
        swap(arr[i], arr[largest]); 
  
        
        heapify(arr, n, largest); 
    } 
} 
  
 
void heapSort(int arr[], int n) 
{ 
    
    for (int i = n / 2 - 1; i &gt;= 0; i--) 
        heapify(arr, n, i); 
  
    
    for (int i=n-1; i&gt;=0; i--) 
    { 

        swap(arr[0], arr[i]); 
  
        
        heapify(arr, i, 0); 
    } 
} 
void printArray(int arr[], int n) 
{ 
    for (int i=0; i&lt;n; ++i) 
        cout &lt;&lt; arr[i] &lt;&lt; " "; 
    cout &lt;&lt; "\n"; 
} 
int main() 
{ 
    int arr[] = {12, 11, 13, 5, 6, 7}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
  
    heapSort(arr, n); 
  
    cout &lt;&lt; "Array ordenado: \n"; 
    printArray(arr, n); 
}
</code></pre><h2 id="radix-sort">Radix Sort</h2><p>Prerrequisito: Counting Sort</p><p>QuickSort, MergeSort e HeapSort são algoritmos de ordenação baseados em comparação. CountSort não é. Tem a complexidade de O(n+k), onde k é o elemento máximo do array de entrada. Portanto, se k é O(n), CountSort se torna ordenação linear, o que é melhor do que algoritmos de ordenação baseados em comparação que possuem complexidade de tempo O(nlogn).</p><p>A ideia é estender o algoritmo CountSort para obter uma melhor complexidade de tempo quando k for O(n2). Aí vem a ideia do Radix Sort.</p><h3 id="o-algoritmo-">O algoritmo:</h3><p>Para cada dígito i onde i varia do dígito menos significativo ao dígito mais significativo de um número, ordene o array de entrada usando o algoritmo countsort de acordo com o i-ésimo dígito. Usamos a countsort porque é uma ordenação estável.	</p><p>Exemplo: Suponha que o array de entrada seja:</p><p>10, 21, 17, 34, 44, 11, 654, 123</p><p>Com base no algoritmo, vamos ordenar o array de entrada de acordo com o dígito das unidades (dígito menos significativo).</p><p>0: 10<br>1: 21 11<br>2:<br>3: 123<br>4: 34 44 654<br>5:<br>6:<br>7: 17<br>8:<br>9:</p><p>Assim, o array se torna 10, 21, 11, 123, 24, 44, 654, 17.</p><p>Agora, vamos ordenar de acordo com o dígito da dezena:</p><p>0:<br>1: 10 11 17<br>2: 21 123<br>3: 34<br>4: 44<br>5: 654<br>6:<br>7:<br>8:<br>9:</p><p>Agora, o array se torna: 10, 11, 17, 21, 123, 34, 44, 654.</p><p>Por fim, ordenamos de acordo com o dígito da centena (dígito mais significativo):</p><p>0: 010 011 017 021 034 044<br>1: 123<br>2:<br>3:<br>4:<br>5:<br>6: 654<br>7:<br>8:<br>9:</p><p>O array se torna: 10, 11, 17, 21, 34, 44, 123, 654, o qual está ordenado. É assim que nosso algoritmo funciona.</p><p>Uma implementação em &nbsp;C:</p><pre><code class="language-c">void countsort(int arr[],int n,int place){

        int i,freq[range]={0};         //o intervalo para números inteiros é 10, pois os dígitos variam de 0 a 9
        int output[n];

        for(i=0;i&lt;n;i++)
                freq[(arr[i]/place)%range]++;

        for(i=1;i&lt;range;i++)
                freq[i]+=freq[i-1];
        
        for(i=n-1;i&gt;=0;i--){
                output[freq[(arr[i]/place)%range]-1]=arr[i];
                freq[(arr[i]/place)%range]--;
        }
        
        for(i=0;i&lt;n;i++)
                arr[i]=output[i];
}

void radixsort(ll arr[],int n,int maxx){            //maxx é o elemento máximo do array

        int mul=1;
        while(maxx){
                countsort(arr,n,mul);
                mul*=10;
                maxx/=10;
        }
}
</code></pre><h2 id="selection-sort">Selection Sort</h2><p>Selection Sort é um dos algoritmos de ordenação mais simples. Esse algoritmo recebe seu nome pela maneira como ele percorre o array ao longo das iterações: ele seleciona o menor elemento atual e o troca de lugar.</p><p>Veja como funciona:</p><ol><li>Encontre o menor elemento no array e troque-o de lugar com o primeiro elemento.</li><li>Encontre o segundo menor elemento e troque com o segundo elemento no array.</li><li>Encontre o terceiro menor elemento e troque com o terceiro elemento no array.</li><li>Repita o processo de encontrar o próximo menor elemento e trocá-lo na posição correta até que todo o array esteja ordenado.</li></ol><p>Mas, como você escreveria o código para encontrar o índice do segundo menor valor em um array?</p><p>Uma maneira fácil é notar que o menor valor já foi trocado para o índice 0, então o problema se reduz a encontrar o menor elemento no array começando no índice 1.</p><p>A ordenação por seleção sempre leva o mesmo número de comparações de chave — N(N − 1)/2.</p><h3 id="implementa-o-em-c-c-">Implementação em C/C++</h3><p>O programa C++ a seguir contém uma implementação iterativa e recursiva do algoritmo Selection Sort. Ambas implementações são invocadas na função <code>main()</code>.</p><pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
using namespace std;

template&lt;typename T, size_t n&gt;
void print_array(T const(&amp;arr)[n]) {
    for (size_t i = 0; i &lt; n; i++)
        std::cout &lt;&lt; arr[i] &lt;&lt; ' ';
    cout &lt;&lt; "\n";
}

int minIndex(int a[], int i, int j) {
    if (i == j)
        return i;
    int k = minIndex(a, i + 1, j);
    return (a[i] &lt; a[k]) ? i : k;
}

void recurSelectionSort(int a[], int n, int index = 0) {
    if (index == n)
        return;
    int k = minIndex(a, index, n - 1);
    if (k != index)
        swap(a[k], a[index]);
    recurSelectionSort(a, n, index + 1);
}

void iterSelectionSort(int a[], int n) {
    for (int i = 0; i &lt; n; i++)
    {
        int min_index = i;
        int min_element = a[i];
        for (int j = i + 1; j &lt; n; j++)
        {
            if (a[j] &lt; min_element)
            {
                min_element = a[j];
                min_index = j;
            }
        }
        swap(a[i], a[min_index]);
    }
}

int main() {
    int recurArr[6] = { 100,35, 500, 9, 67, 20 };
    int iterArr[5] = { 25, 0, 500, 56, 98 };

    cout &lt;&lt; "Selection Sort Recursivo"  &lt;&lt; "\n";
    print_array(recurArr); // 100 35 500 9 67 20
    recurSelectionSort(recurArr, 6);
    print_array(recurArr); // 9 20 35 67 100 500

    cout &lt;&lt; "Selection Sort Iterativo" &lt;&lt; "\n";
    print_array(iterArr); // 25 0 500 56 98
    iterSelectionSort(iterArr, 5);
    print_array(iterArr); // 0 25 56 98 500
}
</code></pre><h3 id="implementa-o-em-javascript-1">Implementação em JavaScript</h3><pre><code class="language-js">function selection_sort(A) {
    var len = A.length;
    for (var i = 0; i &lt; len - 1; i = i + 1) {
        var j_min = i;
        for (var j = i + 1; j &lt; len; j = j + 1) {
            if (A[j] &lt; A[j_min]) {
                j_min = j;
            } else {}
        }
        if (j_min !== i) {
            swap(A, i, j_min);
        } else {}
    }
}

function swap(A, x, y) {
    var temp = A[x];
    A[x] = A[y];
    A[y] = temp;
}
</code></pre><h3 id="implementa-o-em-python">Implementação em Python</h3><pre><code class="language-ps">def selection_sort(arr):
    if not arr:
        return arr
    for i in range(len(arr)):
        min_i = i
        for j in range(i + 1, len(arr)):
            if arr[j] &lt; arr[min_i]:
                min_i = j
        arr[i], arr[min_i] = arr[min_i], arr[i]</code></pre><h3 id="implementa-o-em-java">Implementação em Java</h3><pre><code class="language-java">public void selectionsort(int array[])
{
    int n = array.length;            //método para calcular o tamanho do array 
    for (int i = 0; i &lt; n-1; i++)
    {
        int index = i;
        int min = array[i];          // tomando o elemento min como i-ésimo elemento do array
        for (int j = i+1; j &lt; n; j++)
        {
            if (array[j] &lt; array[index])
            {
                index = j;
                min = array[j];
            }
        }
        int t = array[index];         //Troque os elementos de lugar
        array[index] = array[i];
        array[i] = t;
    }
}
</code></pre><h3 id="implementa-o-em-matlab">Implementação em MATLAB</h3><pre><code>function [sorted] = selectionSort(unsorted)
    len = length(unsorted);
    for i = 1:1:len
        minInd = i;
        for j = i+1:1:len
           if unsorted(j) &lt; unsorted(minInd) 
               minInd = j;
           end
        end
        unsorted([i minInd]) = unsorted([minInd i]);    
    end
    sorted = unsorted;
end
</code></pre><h3 id="propriedades-1">Propriedades</h3><ul><li>Complexidade espacial: &nbsp;<strong>O(n)</strong></li><li>Complexidade temporal: &nbsp;<strong>O(n2)</strong></li><li>Ordenação in loco: &nbsp;<strong>Sim</strong></li><li>Estável: &nbsp;<strong>Não</strong></li></ul><h2 id="bubble-sort">Bubble Sort</h2><p>Assim como as bolhas sobem do fundo de um copo, <strong>bubble sort</strong> é um algoritmo simples que ordena uma lista, permitindo que valores mais baixos ou mais altos borbulhem até o topo. O algoritmo percorre uma lista e compara valores adjacentes, trocando-os se não estiverem na ordem correta.</p><p>Com uma complexidade de pior caso de O(n^2), a ordenação por bolhas é muito lenta em comparação com outros algoritmos de ordenação como o quicksort. A vantagem é que é um dos algoritmos de ordenação mais fáceis de entender e implementar do zero.</p><p>Do ponto de vista técnico, o bubble sort é razoável para ordenar arrays de tamanho pequeno ou, especialmente, ao executar algoritmos de ordenação em computadores com recursos de memória notavelmente limitados.</p><h3 id="exemplo--2">Exemplo:</h3><h3 id="primeira-passagem-pela-lista-">Primeira passagem pela lista:</h3><ul><li>Começando com <code>[4, 2, 6, 3, 9]</code>, o algoritmo compara os dois primeiros elementos no array, 4 e 2. Ele os troca porque 2 &lt; 4: <code>[2, 4, 6, 3, 9]</code></li><li>Ele compara os dois próximos valores, 4 e 6. Como 4 &lt; 6, e estes já estão em ordem, o algoritmo segue em frente: <code>[2, 4, 6, 3, 9]</code></li><li>Os próximos dois valores são trocados, porque 3 &lt; 6: <code>[2, 4, 3, 6, 9]</code></li><li>Os dois últimos valores, 6 e 9, já estão em ordem, então o algoritmo não os troca.</li></ul><h3 id="segunda-passagem-pela-lista-">Segunda passagem pela lista:</h3><ul><li>2 &lt; 4, então não há necessidade de trocar as posições: <code>[2, 4, 3, 6, 9]</code></li><li>O algoritmo troca os próximos dois valores, porque 3 &lt; 4: <code>[2, 3, 4, 6, 9]</code></li><li>Sem trocas, porque 4 &lt; 6: <code>[2, 3, 4, 6, 9]</code></li><li>Novamente, 6 &lt; 9, logo, nenhuma troca ocorre: <code>[2, 3, 4, 6, 9]</code></li></ul><p>A lista já está ordenada, mas o algoritmo bubble sort não percebe isso. Em vez disso, ele precisa concluir uma passagem inteira pela lista sem trocar nenhum valor para saber que a lista está ordenada.</p><h3 id="terceira-passagem-pela-lista-">Terceira passagem pela lista:</h3><ul><li><code>[2, 4, 3, 6, 9]</code> =&gt; <code>[2, 4, 3, 6, 9]</code></li><li><code>[2, 4, 3, 6, 9]</code> =&gt; <code>[2, 4, 3, 6, 9]</code></li><li><code>[2, 4, 3, 6, 9]</code> =&gt; <code>[2, 4, 3, 6, 9]</code></li><li><code>[2, 4, 3, 6, 9]</code> =&gt; <code>[2, 4, 3, 6, 9]</code></li></ul><p>Claramente bubble sort está longe de ser o algoritmo de ordenação mais eficiente. Ainda assim, é simples entender e implementar você mesmo.</p><h4 id="propriedades-2">Propriedades</h4><ul><li>Complexidade espacial: O(1)</li><li>Performance no melhor caso: O(n)</li><li>Performance no caso médio: O(n*n)</li><li>Performance no pior caso: O(n*n)</li><li>Estável: Sim</li></ul><h3 id="explica-o-em-v-deo">Explicação em vídeo</h3><p><a href="https://www.youtube.com/watch?v=Jdtq5uKz-w4">Bubble sort algorithm</a> (em inglês)</p><h3 id="exemplo-em-javascript">Exemplo em JavaScript</h3><pre><code class="language-js">let arr = [1, 4, 7, 45, 7,43, 44, 25, 6, 4, 6, 9],
    sorted = false;

while(!sorted) {
  sorted = true;
  for(var i=0; i &lt; arr.length; i++) {
    if(arr[i] &lt; arr[i-1]) {
      let temp = arr[i];
      arr[i] = arr[i-1];
      arr[i-1] = temp;
      sorted = false;
    }
  }
}
</code></pre><h3 id="exemplo-em-java">Exemplo em Java</h3><pre><code class="language-java">public class BubbleSort {
    static void sort(int[] arr) {
        int n = arr.length;
        int temp = 0;
         for(int i=0; i &lt; n; i++){
                 for(int x=1; x &lt; (n-i); x++){
                          if(arr[x-1] &gt; arr[x]){
                                 temp = arr[x-1];
                                 arr[x-1] = arr[x];
                                 arr[x] = temp;
                         }

                 }
         }

    }
    public static void main(String[] args) {

		for(int i=0; i &lt; 15; i++){
			int arr[i] = (int)(Math.random() * 100 + 1);
		}

                System.out.println("array before sorting\n");
                for(int i=0; i &lt; arr.length; i++){
                        System.out.print(arr[i] + " ");
                }
                bubbleSort(arr);
                System.out.println("\n array after sorting\n");
                for(int i=0; i &lt; arr.length; i++){
                        System.out.print(arr[i] + " ");
                }

        }
}
</code></pre><h3 id="exemplo-em-c-">Exemplo em C++</h3><pre><code class="language-cpp">// Implementação por recursão
void bubblesort(int arr[], int n)
{
	if(n==1)	//Caso inicial
		return;
	bool swap_flag = false;
	for(int i=0;i&lt;n-1;i++)	//Após essa passada, o elemento maior é movido para o local desejado.
	{
		if(arr[i]&gt;arr[i+1])
		{
			int temp=arr[i];
			arr[i]=arr[i+1];
			arr[i+1]=temp;
			swap_flag = true;
		}
	}
        // Se não houver a troca de dois elementos no laço, retorna, pois o array está ordenado
	if(swap_flag == false)
		return;
	bubblesort(arr,n-1);	//Recursão para o restante do array
}
</code></pre><h3 id="exemplo-em-swift">Exemplo em Swift</h3><pre><code class="language-swift">func bubbleSort(_ inputArray: [Int]) -&gt; [Int] {
    guard inputArray.count &gt; 1 else { return inputArray } // Garantir que nosso array de entrada tem mais de 1 elemento
    var numbers = inputArray // Argumentos de função são constantes por padrão em Swift, então fazemos uma cópia
    for i in 0..&lt;(numbers.count - 1) {
        for j in 0..&lt;(numbers.count - i - 1) {
            if numbers[j] &gt; numbers[j + 1] {
                numbers.swapAt(j, j + 1)
            }
        }
    }
    return numbers // retorna o array ordenado
} 
</code></pre><h3 id="exemplo-em-python">Exemplo em Python</h3><pre><code class="language-py">def bubbleSort(arr): 
    n = len(arr) 
    for i in range(n):
        for j in range(0, n-i-1):
                if arr[j] &gt; arr[j+1] : 
                        arr[j], arr[j+1] = arr[j+1], arr[j]
    print(arr)
</code></pre><h3 id="exemplo-em-php">Exemplo em PHP</h3><pre><code class="language-php">function bubble_sort($arr) {
    $size = count($arr)-1;
    for ($i=0; $i&lt;$size; $i++) {
        for ($j=0; $j&lt;$size-$i; $j++) {
            $k = $j+1;
            if ($arr[$k] &lt; $arr[$j]) {
                // Troca os elementos nos índices: $j, $k
                list($arr[$j], $arr[$k]) = array($arr[$k], $arr[$j]);
            }
        }
    }
    return $arr;// retorna o array ordenado
}

$arr = array(1,3,2,8,5,7,4,0);
print("Before sorting");
print_r($arr);

$arr = bubble_sort($arr);
print("After sorting by using bubble sort");
print_r($arr);
</code></pre><h3 id="exemplo-em-c">Exemplo em C</h3><pre><code class="language-c">#include &lt;stdio.h&gt;

int BubbleSort(int array[], int n);

int main(void) {
  int arr[] = {10, 2, 3, 1, 4, 5, 8, 9, 7, 6};
  BubbleSort(arr, 10);

  for (int i = 0; i &lt; 10; i++) {
    printf("%d", arr[i]);
  }
  return 0;
}
int BubbleSort(int array[], n)
{
for (int i = 0 ; i &lt; n - 1; i++)
  {
    for (int j = 0 ; j &lt; n - i - 1; j++)     //n é o tamanho do array
    {
      if (array[j] &gt; array[j+1])      // Para o uso com ordem decrescente 
      {
        int swap   = array[j];
        array[j]   = array[j+1];
        array[j+1] = swap;
      }
    }
  }
}
</code></pre><h2 id="quick-sort">Quick Sort</h2><p>Quick sort é um eficiente algoritmo de ordenação que emprega a técnica de divisão e conquista. A complexidade temporal no caso médio do Quick Sort é O(nlog(n)), sendo O(n^2) no pior caso dependendo da seleção do elemento pivô, que divide o array atual em dois subarrays.</p><p>Por exemplo, a complexidade de tempo do Quick Sort é aproximadamente <code>O(nlog(n))</code> quando a seleção do pivô divide o array original em dois sub arrays de tamanhos quase iguais.</p><p>Por outro lado, se o algoritmo, que seleciona o elemento pivô dos arrays de entrada, produz consistentemente 2 sub-arrays com uma grande diferença em termos de tamanho, o algoritmo de ordenação rápida pode atingir a complexidade temporal de pior caso de O(n^2 ).</p><p>As etapas envolvidas no Quick Sort são:</p><ul><li>Escolha um elemento para servir como pivô, neste caso, o último elemento do array é o pivô.</li><li>Particionamento: Ordene o array de forma que todos os elementos menores que o pivô fiquem à esquerda e todos os elementos maiores que o pivô fiquem à direita.</li><li>Execute o algoritmo recursivamente, levando em consideração o pivô anterior para subdividir adequadamente os arrays esquerdo e direito. (Uma explicação mais detalhada pode ser encontrada nos comentários abaixo)</li></ul><h2 id="exemplos-de-implementa-o-em-v-rias-linguagens">Exemplos de implementação em várias linguagens</h2><h3 id="implementa-o-em-javascript-">Implementação em JavaScript:</h3><pre><code class="language-js">const arr = [6, 2, 5, 3, 8, 7, 1, 4];

const quickSort = (arr, start, end) =&gt; {

  if(start &lt; end) {

    // Você pode aprender sobre como o valor do pivô é derivado nos comentários abaixo
    let pivot = partition(arr, start, end);

    // Certifique-se de ler os comentários abaixo para entender por que pivô - 1 e pivô + 1 são usados
    // Estas são as chamadas recursivas do quickSort
    quickSort(arr, start, pivot - 1);
    quickSort(arr, pivot + 1, end);
  } 

}

const partition = (arr, start, end) =&gt; { 
  let pivot = end;
  // Defina i como start - 1 para que ele possa acessar o primeiro índice no caso de o valor em arr[0] ser maior que arr[pivot]
  // Os comentários abaixo explicarão o comentário acima
  let i = start - 1,
      j = start;

  // Incrementar j até o índice anterior ao pivô
  while (j &lt; pivot) {

    // If the value is greater than the pivot increment j
    if (arr[j] &gt; arr[pivot]) {
      j++;
    }

    // Quando o valor em arr[j] for menor que o pivô:
    // incremente i (arr[i] será um valor maior que arr[pivot]) e troque o valor em arr[i] e arr[j]
    else {
      i++;
      swap(arr, j, i);
      j++;
    }

  }

  //O valor em arr[i + 1] será maior que o valor de arr[pivot]
  swap(arr, i + 1, pivot);

  //Você retorna i + 1, pois os valores à esquerda dele são menores que arr[i+1], e os valores à direita são maiores que arr[i + 1]
  // Dessa forma, quando os quicksorts recursivos são chamados, os novos sub-arrays não incluirão este valor pivô usado anteriormente
  return i + 1;
}

const swap = (arr, firstIndex, secondIndex) =&gt; {
  let temp = arr[firstIndex];
  arr[firstIndex] = arr[secondIndex];
  arr[secondIndex] = temp;
}

quickSort(arr, 0, arr.length - 1);
console.log(arr);
</code></pre><h3 id="implementa-o-em-c">Implementação em C</h3><pre><code class="language-c">#include&lt;stdio.h&gt;  
void swap(int* a, int* b) 
{ 
    int t = *a; 
    *a = *b; 
    *b = t; 
}
int partition (int arr[], int low, int high) 
{ 
    int pivot = arr[high];     
    int i = (low - 1);  
  
    for (int j = low; j &lt;= high- 1; j++) 
    { 
        if (arr[j] &lt;= pivot) 
        { 
            i++;    
            swap(&amp;arr[i], &amp;arr[j]); 
        } 
    } 
    swap(&amp;arr[i + 1], &amp;arr[high]); 
    return (i + 1); 
}
void quickSort(int arr[], int low, int high) 
{ 
    if (low &lt; high) 
    {
        int pi = partition(arr, low, high); 
  
        quickSort(arr, low, pi - 1); 
        quickSort(arr, pi + 1, high); 
    } 
} 
  

void printArray(int arr[], int size) 
{ 
    int i; 
    for (i=0; i &lt; size; i++) 
        printf("%d ", arr[i]); 
    printf("n"); 
} 
  

int main() 
{ 
    int arr[] = {10, 7, 8, 9, 1, 5}; 
    int n = sizeof(arr)/sizeof(arr[0]); 
    quickSort(arr, 0, n-1); 
    printf("Sorted array: n"); 
    printArray(arr, n); 
    return 0; 
} 
</code></pre><h3 id="implementa-o-em-python3">Implementação em Python3</h3><pre><code>import random

z=[random.randint(0,100) for i in range(0,20)]

def quicksort(z):
    if(len(z)&gt;1):        
        piv=int(len(z)/2)
        val=z[piv]
        lft=[i for i in z if i&lt;val]
        mid=[i for i in z if i==val]
        rgt=[i for i in z if i&gt;val]

        res=quicksort(lft)+mid+quicksort(rgt)
        return res
    else:
        return z
        
ans1=quicksort(z)
print(ans1)
</code></pre><h3 id="implementa-o-em-matlab-1">Implementação em MATLAB</h3><pre><code>a = [9,4,7,3,8,5,1,6,2];

sorted = quicksort(a,1,length(a));

function [unsorted] =  quicksort(unsorted, low, high)
    if low &lt; high
        [pInd, unsorted] = partition(unsorted, low, high);
        unsorted = quicksort(unsorted, low, pInd-1);
        unsorted = quicksort(unsorted, pInd+1, high);
    end

end

function [pInd, unsorted] = partition(unsorted, low, high)
    i = low-1;
    for j = low:1:high-1
        if unsorted(j) &lt;= unsorted(high)
            i = i+1;
            unsorted([i,j]) = unsorted([j,i]);
            
        end
    end
    unsorted([i+1,high]) = unsorted([high,i+1]);
    pInd = i+1;

end
</code></pre><p>A complexidade espacial do quick sort é &nbsp;<code>O(n)</code> . Esta é uma melhoria em relação a outros algoritmos de ordenação de divisão e conquista, que têm complexidade espacial de &nbsp;<code>O(nlong(n))</code>.</p><p>Quick sort consegue isso alterando a ordem dos elementos dentro de um determinado array. Compare isso com o algoritmo merge sort que cria 2 arrays, cada um com tamanho <code>n/2</code>, a cada chamada da função.</p><p>No entanto existe o problema deste algoritmo de ordenação ser de tempo <code>O(n*n)</code> &nbsp;se o pivô é sempre mantido no meio. Um problema que pode ser contornado utilizando-se um pivô aleatório</p><h3 id="complexidade">Complexidade</h3><p>O uso de memória no melhor, médio e pior caso corresponde a <strong> </strong>n log(n)n, log(n)n e 2log(n) respectivamente. It's not a stable algorithm, and quicksort is usually done in-place with O(log(n)) stack space.</p><p>A complexidade espacial do quick sort é O(n). Esta é uma melhoria em relação a outros algoritmos de ordenação de divisão e conquista, que ocupam espaço O(n log(n)).</p><h2 id="timsort">Timsort</h2><p>Timsort é um algoritmo de ordenação rápido que trabalha com complexidade O(N log(N)) estável.</p><p>Timsort é uma mistura de Insertion Sort e Mergesort. Esse algoritmo é implementado no método Arrays.sort() em Java, bem como nas funções sorted() e sort() em Python. As partes menores são ordenadas usando o Insertion Sort e posteriormente mescladas usando Mergesort.</p><p>Uma rápida implementação em Python:</p><pre><code class="language-py">def binary_search(the_array, item, start, end):
    if start == end:
        if the_array[start] &gt; item:
            return start
        else:
            return start + 1
    if start &gt; end:
        return start

    mid = round((start + end)/ 2)

    if the_array[mid] &lt; item:
        return binary_search(the_array, item, mid + 1, end)

    elif the_array[mid] &gt; item:
        return binary_search(the_array, item, start, mid - 1)

    else:
        return mid

"""
Insertion sort utilizada pelo timsort se o tamanho do array ou da "run" é pequeno.
"""
def insertion_sort(the_array):
    l = len(the_array)
    for index in range(1, l):
        value = the_array[index]
        pos = binary_search(the_array, value, 0, index - 1)
        the_array = the_array[:pos] + [value] + the_array[pos:index] + the_array[index+1:]
    return the_array

def merge(left, right):
    """Recebe duas listas ordenadas e retorna uma única lista ordenada comparando os elementos um de cada vez.
    [1, 2, 3, 4, 5, 6]
    """
    if not left:
        return right
    if not right:
        return left
    if left[0] &lt; right[0]:
        return [left[0]] + merge(left[1:], right)
    return [right[0]] + merge(left, right[1:])

def timsort(the_array):
    runs, sorted_runs = [], []
    length = len(the_array)
    new_run = [the_array[0]]

    # Para cada i no intervalo de 1 até o tamanho do array
    for i in range(1, length):
        #se i está no final da lista
        if i == length - 1:
            new_run.append(the_array[i])
            runs.append(new_run)
            break
        # se o i-ésimo elemento do array for menor que o anterior
        if the_array[i] &lt; the_array[i-1]:
            # se new_run estiver definido como None (nulo)
            if not new_run:
                runs.append([the_array[i]])
                new_run.append(the_array[i])
            else:
                runs.append(new_run)
                new_run = []
        # senão se for igual ou maior que
        else:
            new_run.append(the_array[i])

    # para cada item em runs, adicione o item usando insertion sort
    for item in runs:
        sorted_runs.append(insertion_sort(item))
    
    # para cada run em sorted_runs, mescle-as
    sorted_array = []
    for run in sorted_runs:
        sorted_array = merge(sorted_array, run)

    print(sorted_array)

timsort([2, 3, 1, 5, 6, 7])
</code></pre><h3 id="complexidade-">Complexidade:</h3><p>Tim sort tem uma complexidade estável de O(N log(N)) e se compara muito bem com Quicksort. Uma comparação de complexidades pode ser encontrada neste <a href="https://cdn-images-1.medium.com/max/1600/1*1CkG3c4mZGswDShAV9eHbQ.png">gráfico</a>.</p><h2 id="merge-sort">Merge Sort</h2><p>Merge Sort é um algoritmo que emprega a técnica de <a href="https://guide.freecodecamp.org/algorithms/divide-and-conquer-algorithms">divisão e conquista</a>. Ele divide o array de entrada em duas metades, chama a si mesmo pelas duas metades e depois mescla as duas metades já ordenadas. A maior parte do algoritmo recebe dois arrays ordenados, e temos que mesclá-los em um único array ordenado. Todo o processo de ordenação de um array de N inteiros pode ser resumido em três etapas:</p><ul><li>Dividir o array em duas metades.</li><li>Ordene a metade esquerda e a metade direita usando o mesmo algoritmo recursivamente.</li><li>Mescle as metades ordenadas.</li></ul><p>Existe um algoritmo chamado <a href="https://en.wikipedia.org/wiki/Cheney%27s_algorithm">Two Finger Algorithm</a> que nos ajuda a mesclar dois arrays ordenados. Usar essa sub-rotina e chamar a função merge sort nas metades do array recursivamente nos dará o array ordenado final que estamos procurando.</p><p>Como este é um algoritmo baseado em recursão, temos uma relação de recorrência para ele. Uma relação de recorrência é simplesmente uma maneira de representar um problema em termos de seus subproblemas.</p><p><code>T(n) = 2 * T(n / 2) + O(n)</code></p><p>Colocando em linguagem simples, dividimos o subproblema em duas partes em cada etapa e temos uma quantidade linear de trabalho que precisamos realizar para mesclar as duas metades ordenadas em cada etapa.</p><h3 id="complexidade-1">Complexidade</h3><p>A maior vantagem de usar Merge sort é que a <a href="https://www.youtube.com/watch?v=V42FBiohc6c&amp;list=PL2_aWCzGMAwI9HK8YPVBjElbLbI3ufctn" rel="nofollow">complexidade temporal</a> é apenas n*log(n) para ordenar um array inteiro. É muito melhor do que a complexidade temporal de n^2 de execução de bubble sort ou insertion sort.</p><p>Antes de escrevermos o código, vamos entender como a ordenação por mesclagem funciona com a ajuda de um diagrama.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/06/4712ef1a5d856dbb4af393fcc08a820a38787395.png" class="kg-image" alt="4712ef1a5d856dbb4af393fcc08a820a38787395" width="600" height="400" loading="lazy"></figure><ul><li>Inicialmente temos um array de 6 inteiros não ordenados Arr(5, 8, 3, 9, 1, 2)</li><li>Dividimos o array em duas metades Arr1 = (5, 8, 3) e Arr2 = (9, 1, 2).</li><li>Novamente, nós os dividimos em duas metades: Arr3 = (5, 8) e Arr4 = (3) e Arr5 = (9, 1) e Arr6 = (2).</li><li>Novamente, nós os dividimos em duas metades: Arr7 = (5), Arr8 = (8), Arr9 = (9), Arr10 = (1) e Arr6 = (2).</li><li>Vamos agora comparar os elementos nesses sub-arrays para mesclá-los.</li></ul><h3 id="propriedades--1">Propriedades:</h3><ul><li>Complexidade espacial: O(n)</li><li>Complexidade temporal: O(n*log(n)). A complexidade temporal para o Merge Sort pode não ser óbvia à primeira vista. O fator log(n) entra por causa da relação de recorrência que mencionamos anteriormente.</li><li>Ordenação in-loco: Não em uma implementação típica</li><li>Estável: Sim</li><li>Paralelizável :sim (diversas variantes paralelas são discutidas na terceira edição do livro Introduction to Algorithms Cormen de Leiserson, Rivest, and Stein.)</li></ul><h3 id="implementa-o-em-c--1"><strong>Implementação em C++</strong></h3><pre><code class="language-cpp">void merge(int array[], int left, int mid, int right)
{
    int i, j, k;

    // tamanho do sub-array esquerdo
int size_left = mid - left + 1;

// tamanho do sub-array direito
int size_right =  right - mid;

/* Criar arrays temporários */
int Left[size_left], Right[size_right];

/* Copiar dados para os arrays temporários L[] e R[] */
for(i = 0; i &lt; size_left; i++)
{
    Left[i] = array[left+i];
}

for(j = 0; j &lt; size_right; j++)
{
    Right[j] = array[mid+1+j];
}

// Mesclar os arrays temporários de volta no arr[left..right]
i = 0; // índice inicial do sub-array esquerdo
j = 0; // índice inicial do sub-array direito
k = left; // índice inicial do array mesclado

while (i &lt; size_left &amp;&amp; j &lt; size_right)
{
    if (Left[i] &lt;= Right[j])
    {
        array[k] = Left[i];
        i++;
    }
    else
    {
        array[k] = Right[j];
        j++;
    }
    k++;
}

// Copiar os elementos restantes de Left[]
while (i &lt; size_left)
{
    array[k] = Left[i];
    i++;
    k++;
}

// Copiar os elementos restantes de R[]
while (j &lt; size_right)
{
    array[k] = Right[j];
    j++;
    k++;
}
}

void mergeSort(int array[], int left, int right)
{
    if(left &lt; right)
    {
        int mid = (left+right)/2;

        // Ordenar a primeira e a segunda metade
    mergeSort(array, left, mid);
    mergeSort(array, mid+1, right);

    // Finalmente, mesclá-las
    merge(array, left, mid, right);
}
}</code></pre><h3 id="implementa-o-em-javascript-2"><strong>Implementação em JavaScript</strong></h3><pre><code class="language-js">function mergeSort (arr) {
  if (arr.length &lt; 2) return arr;
  var mid = Math.floor(arr.length /2);
  var subLeft = mergeSort(arr.slice(0,mid));
  var subRight = mergeSort(arr.slice(mid));
  return merge(subLeft, subRight);
}</code></pre><p>Primeiro, verificamos o comprimento do array. Se for 1, simplesmente retornamos o array. Este seria o nosso caso base. Caso contrário, descobriremos o valor do meio e dividiremos o array em duas metades. Agora vamos ordenar ambas metades com chamadas recursivas da função MergeSort.</p><pre><code class="language-js">function merge (a,b) {
    var result = [];
    while (a.length &gt;0 &amp;&amp; b.length &gt;0)
        result.push(a[0] &lt; b[0]? a.shift() : b.shift());
    return result.concat(a.length? a : b);
}</code></pre><p>Quando mesclamos as duas metades, armazenamos o resultado em um array auxiliar. Vamos comparar o elemento inicial do array esquerdo com o elemento inicial do array direito. O que for menor será enviado para o array de resultados e o removeremos dos respectivos arrays usando o operador [shift() . Se ainda restarem valores no array esquerdo ou direito, simplesmente o concatenamos no final do resultado. Aqui está o resultado ordenado:</p><pre><code class="language-js">var test = [5,6,7,3,1,3,15];
console.log(mergeSort(test));

&gt;&gt; [1, 3, 3, 5, 6, 7, 15]</code></pre><h3 id="um-tutorial-sobre-merge-sort-no-youtube">Um tutorial sobre Merge Sort no YouTube</h3><p>Aqui está um bom vídeo do YouTube <a href="https://www.youtube.com/watch?v=TzeBrDU-JaY">que aborda o tópico em detalhes</a> (em inglês).</p><h3 id="implementa-o-em-js">Implementação em JS</h3><pre><code class="language-js">const list = [23, 4, 42, 15, 16, 8, 3]

const mergeSort = (list) =&gt;{
  if(list.length &lt;= 1) return list;
  const middle = list.length / 2 ;
  const left = list.slice(0, middle);
  const right = list.slice(middle, list.length);
  return merge(mergeSort(left), mergeSort(right));
}

const merge = (left, right) =&gt; {
  var result = [];
  while(left.length || right.length) {
    if(left.length &amp;&amp; right.length) {
      if(left[0] &lt; right[0]) {
        result.push(left.shift())
      } else {
        result.push(right.shift())
      }
    } else if(left.length) {
        result.push(left.shift())
      } else {
        result.push(right.shift())
      }
    }
  return result;
}

console.log(mergeSort(list)) // [ 3, 4, 8, 15, 16, 23, 42 ]
</code></pre><h3 id="implementa-o-em-c-1">Implementação em C</h3><pre><code class="language-c">#include&lt;stdlib.h&gt; 
#include&lt;stdio.h&gt;
void merge(int arr[], int l, int m, int r) 
{ 
    int i, j, k; 
    int n1 = m - l + 1; 
    int n2 =  r - m; 
  
    
    int L[n1], R[n2]; 
  
    for (i = 0; i &lt; n1; i++) 
        L[i] = arr[l + i]; 
    for (j = 0; j &lt; n2; j++) 
        R[j] = arr[m + 1+ j];
    i = 0; 
    j = 0; 
    k = l; 
    while (i &lt; n1 &amp;&amp; j &lt; n2) 
    { 
        if (L[i] &lt;= R[j]) 
        { 
            arr[k] = L[i]; 
            i++; 
        } 
        else
        { 
            arr[k] = R[j]; 
            j++; 
        } 
        k++; 
    } 
  
    
    while (i &lt; n1) 
    { 
        arr[k] = L[i]; 
        i++; 
        k++; 
    } 
  
    while (j &lt; n2) 
    { 
        arr[k] = R[j]; 
        j++; 
        k++; 
    } 
} 
  
void mergeSort(int arr[], int l, int r) 
{ 
    if (l &lt; r) 
    {  
        int m = l+(r-l)/2; 
  
        
        mergeSort(arr, l, m); 
        mergeSort(arr, m+1, r); 
  
        merge(arr, l, m, r); 
    } 
}
void printArray(int A[], int size) 
{ 
    int i; 
    for (i=0; i &lt; size; i++) 
        printf("%d ", A[i]); 
    printf("\n"); 
} 
int main() 
{ 
    int arr[] = {12, 11, 13, 5, 6, 7}; 
    int arr_size = sizeof(arr)/sizeof(arr[0]); 
  
    printf("Given array is \n"); 
    printArray(arr, arr_size); 
  
    mergeSort(arr, 0, arr_size - 1); 
  
    printf("\nSorted array is \n"); 
    printArray(arr, arr_size); 
    return 0; 
</code></pre><h3 id="implementa-o-em-c--2">Implementação em C++</h3><p>Vamos considerar o array A = {2,5,7,8,9,12,13} e array B = {3,5,6,9,15} e queremos que o array C esteja ordenado em ordem crescente também.</p><pre><code class="language-cpp">void mergesort(int A[],int size_a,int B[],int size_b,int C[])
{
     int token_a,token_b,token_c;
     for(token_a=0, token_b=0, token_c=0; token_a&lt;size_a &amp;&amp; token_b&lt;size_b; )
     {
          if(A[token_a]&lt;=B[token_b])
               C[token_c++]=A[token_a++];
          else
               C[token_c++]=B[token_b++];
      }
      
      if(token_a&lt;size_a)
      {
          while(token_a&lt;size_a)
               C[token_c++]=A[token_a++];
      }
      else
      {
          while(token_b&lt;size_b)
               C[token_c++]=B[token_b++];
      }

}
</code></pre><h3 id="implementa-o-em-python-1">Implementação em Python</h3><pre><code class="language-py">def merge(left,right,compare):
	result = [] 
	i,j = 0,0
	while (i &lt; len(left) and j &lt; len(right)):
		if compare(left[i],right[j]):
			result.append(left[i])
			i += 1
		else:
			result.append(right[j])
			j += 1
	while (i &lt; len(left)):
		result.append(left[i])
		i += 1
	while (j &lt; len(right)):
		result.append(right[j])
		j += 1
	return result

def merge_sort(arr, compare = lambda x, y: x &lt; y):
     #Função lambda usada para ordenar um array em ordem crescente e decrescente.
     #Por padrão, ela ordena o array em ordem crescente
	if len(arr) &lt; 2:
		return arr[:]
	else:
		middle = len(arr) // 2
		left = merge_sort(arr[:middle], compare)
		right = merge_sort(arr[middle:], compare)
		return merge(left, right, compare) 

arr = [2,1,4,5,3]
print(merge_sort(arr))
</code></pre><h3 id="implementa-o-em-java-1">Implementação em Java</h3><pre><code class="language-java">public class mergesort {

	public static int[] mergesort(int[] arr,int lo,int hi) {
		
		if(lo==hi) {
			int[] ba=new int[1];
			ba[0]=arr[lo];
			return ba;
		}
		
		int mid=(lo+hi)/2;
		int arr1[]=mergesort(arr,lo,mid);
		int arr2[]=mergesort(arr,mid+1,hi);
		return merge(arr1,arr2);
	}
	
	public static int[] merge(int[] arr1,int[] arr2) {
		int i=0,j=0,k=0;
		int n=arr1.length;
		int m=arr2.length;
		int[] arr3=new int[m+n];
		while(i&lt;n &amp;&amp; j&lt;m) {
			if(arr1[i]&lt;arr2[j]) {
				arr3[k]=arr1[i];
				i++;
			}
			else {
				arr3[k]=arr2[j];
				j++;
			}
			k++;
		}
		
		while(i&lt;n) {
			arr3[k]=arr1[i];
			i++;
			k++;
		}
		
		while(j&lt;m) {
			arr3[k]=arr2[j];
			j++;
			k++;
		}
		
		return arr3;
		
	}
	
	public static void main(String[] args) {
		int arr[]= {2,9,8,3,6,4,10,7};
		int[] so=mergesort(arr,0,arr.length-1);
		for(int i=0;i&lt;arr.length;i++)
			System.out.print(so[i]+" ");
	}

}
</code></pre><h3></h3> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Algoritmo de caminho de custo mínimo de Dijkstra - uma introdução detalhada e visual ]]>
                </title>
                <description>
                    <![CDATA[ Boas-vindas! Se você sempre quis aprender e entender o algoritmo de Dijkstra, este artigo é para você. Você verá como ele funciona nos bastidores com uma explicação gráfica passo a passo. Você aprenderá:  * Conceitos básicos sobre grafos (uma breve revisão).  * Para que o algoritmo de Dijkstra ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/algoritmo-de-caminho-de-custo-minimo-de-dijkstra-uma-introducao-detalhada-e-visual/</link>
                <guid isPermaLink="false">6212c18d06c4bd05013004d1</guid>
                
                    <category>
                        <![CDATA[ Algoritmos ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Cayo Dias ]]>
                </dc:creator>
                <pubDate>Sun, 27 Mar 2022 14:51:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/Algorithm-Image-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/dijkstras-shortest-path-algorithm-visual-introduction/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Dijkstra's Shortest Path Algorithm - A Detailed and Visual Introduction</a>
      </p><p><strong>Boas-vindas!</strong> Se você sempre quis aprender e entender o algoritmo de Dijkstra, este artigo é para você. Você verá como ele funciona nos bastidores com uma explicação gráfica passo a passo.</p><p><strong>Você aprenderá:</strong></p><ul><li>Conceitos básicos sobre grafos (uma breve revisão).</li><li>Para que o algoritmo de Dijkstra é utilizado.</li><li>Como o algoritmo funciona através de um exemplo passo a passo.</li></ul><p><strong>Vamos começar. ✨</strong></p><h2 id="-introdu-o-aos-grafos">🔹 Introdução aos grafos</h2><p>Vamos começar com uma breve introdução aos grafos.</p><h3 id="conceitos-b-sicos">Conceitos básicos</h3><p>Grafos são estruturas de dados usadas para representar "conexões" entre pares de elementos.</p><ul><li>Esses elementos são chamados de nós (ou vértices). Eles representam objetos, pessoas ou entidades da vida real.</li><li>As conexões entre os nós são chamadas de arestas.</li></ul><p>Esta é uma representação gráfica de um grafo:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-123.png" class="kg-image" alt="image-123" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-123.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-123.png 832w" width="832" height="392" loading="lazy"></figure><p>Os <strong>nós</strong> são representados por círculos coloridos e as <strong>arestas</strong> são representadas por linhas que conectam esses círculos.</p><p><strong>💡 Dica: </strong>dois nós estarão conectados se houver uma aresta entre eles.</p><h3 id="aplica-es">Aplicações</h3><p>Os grafos são diretamente aplicáveis a cenários do mundo real. Por exemplo, poderíamos usá-los para modelar uma rede de transporte, onde os nós representariam instalações que enviam ou recebem produtos e arestas representariam estradas ou caminhos que os conectam (veja abaixo).</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-121.png" class="kg-image" alt="image-121" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-121.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-121.png 883w" width="883" height="491" loading="lazy"><figcaption>Rede representada por um grafo</figcaption></figure><h3 id="tipos-de-grafos">Tipos de grafos</h3><p>Os grafos podem ser:</p><ul><li><strong>Não dirigidos: </strong>se para cada par de nós conectados, você pode ir de um nó para o outro em ambas as direções.</li><li><strong>Dirigidos: </strong>se para cada par de nós conectados, você só pode ir de um nó para outro em uma direção específica. Usamos setas em vez de linhas simples para representar arestas dirigidas.</li></ul><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-124.png" class="kg-image" alt="image-124" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-124.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-124.png 997w" width="997" height="395" loading="lazy"><figcaption>Na caixa à esquerda: "Não dirigido" | Na caixa à direita: "Dirigido"</figcaption></figure><p><strong>💡 Dica:</strong> neste artigo, abordaremos grafos <strong>não dirigidos</strong>.</p><h3 id="grafos-ponderados">Grafos ponderados</h3><p>Um <strong>grafo ponderado</strong> é um grafo cujas arestas têm um "peso" ou "custo". O peso de uma aresta pode representar distância, tempo ou qualquer coisa que modele a "conexão" entre o par de nós que ela conecta.</p><p>Por exemplo, no grafo ponderado abaixo, você pode ver um número em azul próximo de cada aresta. Este número é usado para representar o peso da aresta correspondente.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-126.png" class="kg-image" alt="image-126" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-126.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-126.png 785w" width="785" height="316" loading="lazy"></figure><p><strong>💡 Dica:</strong> esses pesos são essenciais para o Algoritmo de Dijkstra. Você verá por que a seguir.</p><h2 id="-introdu-o-ao-algoritmo-de-dijkstra">🔸 Introdução ao algoritmo de Dijkstra</h2><p>Agora que você conhece os conceitos básicos de grafos, vamos nos aprofundar nesse algoritmo incrível.</p><ul><li>Propósito e casos de uso</li><li>História</li><li>Elementos básicos do algoritmo</li><li>Requisitos</li></ul><h3 id="prop-sito-e-casos-de-uso">Propósito e casos de uso</h3><p>Com o algoritmo de Dijkstra, você poderá encontrar o caminho de menor custo entre nós em um grafo. Particularmente, você poderá <strong>encontrar o caminho de menor custo entre um nó (denominado “origem”) e todos os outros nós do grafo</strong>, produzindo uma árvore de custo-mínimo.</p><p>Este algoritmo é usado em dispositivos GPS para encontrar o caminho mais curto entre a localização atual e o destino. Ele possui ampla aplicação na indústria, principalmente em domínios que requerem modelagem de redes</p><h3 id="hist-ria">História</h3><p>Este algoritmo foi criado e publicado pelo <a href="https://pt.wikipedia.org/wiki/Edsger_Dijkstra">Dr. Edsger W. Dijkstra</a>, um brilhante cientista da computação e engenheiro de software holandês.</p><p>Em 1959, ele publicou um artigo de 3 páginas intitulado "A note on two problems in connexion with graphs" (Uma nota sobre dois problemas em conexão com grafos, em tradução livre), onde explicou seu novo algoritmo.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-112.png" class="kg-image" alt="image-112" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-112.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/03/image-112.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-112.png 1200w" sizes="(min-width: 720px) 720px" width="1200" height="822" loading="lazy"><figcaption><a href="https://commons.wikimedia.org/wiki/File:Edsger_Dijkstra_1994.jpg">Dr. Edsger Dijkstra</a> na <a href="https://pt.wikipedia.org/wiki/Instituto_Federal_de_Tecnologia_de_Zurique">ETH Zurich</a>, em 1994 (foto: Andreas F. Borchert)</figcaption></figure><p>Durante uma entrevista em 2001, o dr. Dijkstra revelou como e por que desenvolveu o algoritmo:</p><blockquote>Qual é o caminho mais curto para viajar de Roterdã a Groningen? É o algoritmo para o caminho mais curto, que projetei em aproximadamente 20 minutos. Certa manhã, eu estava fazendo compras em Amsterdã com minha noiva e, cansado, sentamos no terraço do café para beber uma xícara de café e eu estava pensando se poderia fazer isso, e então, desenvolvi o algoritmo para o caminho mais curto . Como eu disse, foi uma invenção de 20 minutos. Na verdade, foi publicado em 1959, três anos depois. A publicação continua bem legal. Uma das razões por que ela é tão legal foi que eu a desenhei sem lápis e papel. Sem lápis e papel, você é quase forçado a evitar todas as complexidades evitáveis. Eventualmente, esse algoritmo se tornou, para minha grande surpresa, um dos pilares da minha fama. — Conforme citado no artigo <a href="https://en.wikipedia.org/wiki/Edsger_W._Dijkstra">Edsger W. Dijkstra</a> em <a href="https://dl.acm.org/doi/pdf/10.1145/1787234.1787249">An interview with Edsger W. Dijkstra</a> (Uma entrevista com Edsger W. Dijkstra).</blockquote><p>⭐ <strong>Inacreditável, não?</strong> Em apenas 20 minutos, o Dr. Dijkstra desenvolveu um dos algoritmos mais famosos da história da Ciência da Computação.</p><h3 id="no-es-b-sicas-do-algoritmo-de-dijkstra">Noções básicas do algoritmo de Dijkstra</h3><ul><li>O Algoritmo de Dijkstra basicamente começa no nó que você escolhe (o nó de origem) e analisa o grafo para encontrar o caminho de menor custo entre esse nó e todos os outros nós do grafo.</li><li>O algoritmo mantém o registro da distância mais curta atualmente conhecida de cada nó até o nó de origem e atualiza esses valores se encontrar um caminho de menor custo.</li><li>Uma vez que o algoritmo encontrou o caminho de menor custo entre o nó de origem e outro nó, esse nó é marcado como "visitado" e adicionado ao caminho.</li><li>O processo continua até que todos os nós do grafo tenham sido adicionados ao caminho. Desta forma, temos um caminho que conecta o nó de origem a todos os outros nós seguindo o caminho de menor custo possível para chegar a cada nó.</li></ul><h3 id="requisitos">Requisitos</h3><p>O Algoritmo de Dijkstra só funciona com grafos com pesos positivos. Isso porque, durante o processo, os pesos das arestas devem ser somados para encontrar o caminho de menor custo.</p><p>Se houver um peso negativo no grafo, o algoritmo não funcionará corretamente. Uma vez que um nó tenha sido marcado como "visitado", o caminho atual para esse nó é marcado como o caminho de menor custo para chegar a esse nó. E pesos negativos podem alterar isso se o peso total puder ser decrementado após essa etapa ter ocorrido.</p><h2 id="-exemplo-do-algoritmo-de-dijkstra">🔹 Exemplo do algoritmo de Dijkstra</h2><p>Agora que você sabe mais sobre esse algoritmo, vamos ver como ele funciona nos bastidores com um exemplo passo a passo.</p><p>Temos este grafo:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-76-1.png" class="kg-image" alt="image-76-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-76-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-76-1.png 921w" width="921" height="383" loading="lazy"></figure><p>O algoritmo gerará o caminho de menor custo (neste caso, o caminho mais curto) do nó 0 para todos os outros nós do grafo.</p><p><strong>💡 Dica: </strong>neste caso, assumiremos que o peso das arestas representa a distância entre dois nós.</p><p>Teremos o caminho mais curto do nó <code>0</code> ao nó <code>1</code>, do nó <code>0</code> ao nó <code>2</code>, do nó <code>0</code> ao nó <code>3</code>, e assim por diante para cada nó do grafo.</p><p>Inicialmente, temos esta lista de distâncias (veja a lista abaixo):</p><ul><li>A distância do nó de origem até ele mesmo é 0. Para este exemplo, o nó de origem será o nó 0, mas pode ser qualquer nó que você escolher.</li><li>A distância do nó de origem para todos os outros nós ainda não foi determinada, então usamos o símbolo do infinito para representar isso inicialmente.</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-77-1.png" class="kg-image" alt="image-77-1" width="226" height="341" loading="lazy"><figcaption>Tabela de distâncias entre o nó 0 e os demais nós</figcaption></figure><p>Também temos esta lista (veja abaixo) para acompanhar os nós que ainda não foram visitados (nós que não foram incluídos no caminho):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-78-1.png" class="kg-image" alt="image-78-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-78-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-78-1.png 816w" sizes="(min-width: 720px) 720px" width="816" height="103" loading="lazy"><figcaption>Lista de nós não visitados.</figcaption></figure><p><strong>💡 Dica: </strong>lembre-se de que o algoritmo é concluído quando todos os nós forem adicionados ao caminho.</p><p>Como estamos escolhendo começar no nó <code>0</code>, podemos marcar esse nó como visitado. De forma equivalente, nós o cortamos da lista de nós não visitados e adicionamos uma borda vermelha ao nó correspondente no diagrama:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-87.png" class="kg-image" alt="image-87" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-87.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-87.png 734w" sizes="(min-width: 720px) 720px" width="734" height="53" loading="lazy"></figure><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-83-1.png" class="kg-image" alt="image-83-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-83-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-83-1.png 876w" width="876" height="418" loading="lazy"></figure><p>Agora precisamos verificar a distância do nó <code>0</code> até seus nós adjacentes. Como você pode ver, estes são os nós &nbsp;<code>1</code> e <code>2</code> (veja as bordas vermelhas):</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-89.png" class="kg-image" alt="image-89" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-89.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-89.png 962w" width="962" height="377" loading="lazy"></figure><p><strong>💡 Dica:</strong> isso não significa que estamos adicionando imediatamente os dois nós adjacentes ao caminho mais curto. Antes de adicionar um nó a este caminho, precisamos verificar se encontramos o caminho mais curto para alcançá-lo. Estamos simplesmente fazendo um processo de exame inicial para ver as opções disponíveis.</p><p>Precisamos atualizar as distâncias do nó <code>0</code> ao <code>1</code> e ao nó <code>2</code> com os pesos das arestas que os conectam ao nó <code>0</code> (origem). Estes pesos são 2 e 6, respectivamente:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-90.png" class="kg-image" alt="image-90" width="198" height="292" loading="lazy"></figure><p>Após atualizar as distâncias dos nós adjacentes, precisamos:</p><ul><li>Selecionar o nó mais próximo do nó de origem com base nas distâncias conhecidas atuais.</li><li>Marcá-lo como visitado.</li><li>Adicioná-lo ao caminho.</li></ul><p>Se verificarmos a lista de distâncias, podemos ver que o nó <code>1</code> tem a menor distância até a origem (distância igual a 2), então, nós o adicionamos ao caminho.</p><p>No diagrama, podemos representar isso com uma aresta vermelha:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-94.png" class="kg-image" alt="image-94" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-94.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-94.png 958w" width="958" height="412" loading="lazy"></figure><p>Marcamos com um quadrado vermelho na lista para representar que foi "visitado" e que encontramos o caminho mais curto para este nó:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-92.png" class="kg-image" alt="image-92" width="224" height="308" loading="lazy"></figure><p>Riscamos da lista de nós não visitados:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-93.png" class="kg-image" alt="image-93" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-93.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-93.png 601w" width="601" height="82" loading="lazy"></figure><p>Agora, precisamos analisar os novos nós adjacentes para encontrar o caminho mais curto para alcançá-los. Analisaremos apenas os nós que são adjacentes aos nós que já fazem parte do caminho mais curto (o caminho marcado com arestas vermelhas).</p><p>Os nós <code>3</code> e <code>2</code> são ambos adjacentes aos nós que já estão no caminho porque estão diretamente conectados aos nós<code>1</code> e <code>0</code>, respectivamente, como você pode ver abaixo. Esses são os nós que analisaremos na próxima etapa.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-94--1-.png" class="kg-image" alt="image-94--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-94--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-94--1-.png 958w" width="958" height="412" loading="lazy"></figure><p>Como já temos a distância do nó de origem ao nó <code>2</code> anotado em nossa lista, não precisamos atualizar a distância desta vez. Precisamos apenas atualizar a distância do nó de origem ao novo nó adjacente (o nó <code>3</code>):</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-98.png" class="kg-image" alt="image-98" width="205" height="288" loading="lazy"></figure><p>Essa distância é igual a <strong>7</strong>. Vamos ver o porquê.</p><p>Para encontrar a distância do nó de origem para outro nó (neste caso, nó <code>3</code>), somamos os pesos de todas as arestas que formam o caminho mais curto para chegar a esse nó:</p><ul><li><strong>No caso do nó <code>3</code>:</strong> a distância total é <strong>7</strong> porque adicionamos os pesos das arestas que formam o caminho<code>0 -&gt; 1 -&gt; 3</code> (2 &nbsp;para a aresta <code>0 -&gt; 1</code> e 5 para a aresta <code>1 -&gt; 3</code>).</li></ul><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-94--2-.png" class="kg-image" alt="image-94--2-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-94--2-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-94--2-.png 958w" width="958" height="412" loading="lazy"></figure><p>Agora que temos a distância até os nós adjacentes, temos que escolher qual nó será adicionado ao caminho. Devemos selecionar o nó <strong>não visitado</strong> com a distância mais curta (atualmente conhecida) até o nó de origem.</p><p>A partir da lista de distâncias, podemos detectar imediatamente que este é um nó <code>2</code> cuja distância é <strong>6</strong>:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-98--1-.png" class="kg-image" alt="image-98--1-" width="205" height="288" loading="lazy"></figure><p>Adicionamos ao caminho graficamente com uma borda vermelha ao redor do nó e uma aresta vermelha:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-96.png" class="kg-image" alt="image-96" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-96.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-96.png 932w" width="932" height="389" loading="lazy"></figure><p>Também o marcamos como visitado adicionando um pequeno quadrado vermelho na lista de distâncias e riscando-o da lista de nós não visitados:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-99.png" class="kg-image" alt="image-99" width="221" height="292" loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-100.png" class="kg-image" alt="image-100" width="516" height="68" loading="lazy"></figure><p>Agora precisamos repetir o processo para encontrar o caminho mais curto do nó de origem até o novo nó adjacente, que é o nó <code>3</code>.</p><p>Você pode ver que temos dois caminhos possíveis <code>0 -&gt; 1 -&gt; 3</code> ou <code>0 -&gt; 2 -&gt; 3</code>. Vamos ver como podemos decidir qual é o caminho mais curto.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-96--1-.png" class="kg-image" alt="image-96--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-96--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-96--1-.png 932w" width="932" height="389" loading="lazy"></figure><p>O nó <code>3</code> já possui uma distância na lista que foi registrada anteriormente (7, veja a lista abaixo). Essa distância foi resultado de um passo anterior, onde somamos os pesos 5 e 2 das duas arestas que precisávamos cruzar para seguir o caminho <code>0 -&gt; 1 -&gt; 3</code>.</p><p>Mas agora temos outra alternativa. Se escolhermos seguir o caminho<code>0 -&gt; 2 -&gt; 3</code>, precisaríamos seguir duas arestas <code>0 -&gt; 2</code> e <code>2 -&gt; 3</code> com pesos <strong>6</strong> e <strong>8</strong>,<strong> </strong>respectivamente,<strong> </strong>o que representa uma distância total igual a 14.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-101.png" class="kg-image" alt="image-101" width="514" height="294" loading="lazy"></figure><p>Claramente, a primeira distância (existente) é menor (7 x 14), então escolheremos manter o caminho original <code>0 -&gt; 1 -&gt; 3</code>. <strong>Só atualizamos a distância se o novo caminho for mais curto</strong>.</p><p>Portanto, adicionamos este nó ao caminho usando a primeira alternativa: <code>0 -&gt; 1 -&gt; 3</code>.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-104.png" class="kg-image" alt="image-104" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-104.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-104.png 933w" width="933" height="415" loading="lazy"></figure><p>Marcamos este nó como visitado e o riscamos da lista de nós não visitados:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-103.png" class="kg-image" alt="image-103" width="204" height="292" loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-106.png" class="kg-image" alt="image-106" width="576" height="71" loading="lazy"></figure><p>Agora, repetimos esse processo.</p><p>Precisamos verificar os novos nós adjacentes que não visitamos até agora. Desta vez, esses nós são os nós <code>4</code> e <code>5</code>, já que ambos são adjacentes ao nó <code>3</code>.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-104--1-.png" class="kg-image" alt="image-104--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-104--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-104--1-.png 933w" width="933" height="415" loading="lazy"></figure><p>Atualizamos as distâncias desses nós até o nó de origem, sempre tentando encontrar um caminho mais curto, se possível:</p><ul><li><strong>No caso do nó <code>4</code>:</strong> a distância é <strong>17</strong> para o caminho &nbsp;<code>0 -&gt; 1 -&gt; 3 -&gt; 4</code>.</li><li><strong>No caso do nó <code>5</code>:</strong> a distância é <strong>22</strong> para o caminho <code>0 -&gt; 1 -&gt; 3 -&gt; 5</code>.</li></ul><p><strong>💡 Dica:</strong> Observe que só podemos considerar estender o caminho mais curto (marcado em vermelho). Não podemos considerar caminhos que nos levarão através de arestas que não foram adicionadas ao caminho mais curto (por exemplo, não podemos formar um caminho que passe pela aresta<code>2 -&gt; 3</code>).</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-105.png" class="kg-image" alt="image-105" width="350" height="298" loading="lazy"></figure><p>Precisamos escolher qual nó não visitado será marcado como visitado. Neste caso, é o nó <code>4</code> porque tem a distância mais curta na lista de distâncias. Adicionamos graficamente no diagrama:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-108.png" class="kg-image" alt="image-108" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-108.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-108.png 887w" width="887" height="403" loading="lazy"></figure><p>Também o marcamos como "visitado" adicionando um pequeno quadrado vermelho na lista:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-107.png" class="kg-image" alt="image-107" width="202" height="292" loading="lazy"></figure><p>E o riscamos da lista de nós não visitados:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-109.png" class="kg-image" alt="image-109" width="580" height="80" loading="lazy"></figure><p>E repetimos o processo novamente. Verificamos os nós adjacentes: nós <code>5</code> e <code>6</code>. Precisamos analisar cada caminho possível que podemos seguir para alcançá-los a partir de nós que já foram marcados como visitados e adicionados ao caminho.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-108--1-.png" class="kg-image" alt="image-108--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-108--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-108--1-.png 887w" width="887" height="403" loading="lazy"></figure><p><strong>No caso do nó <code>5</code>:</strong></p><ul><li>A primeira opção é seguir o caminho <code>0 -&gt; 1 -&gt; 3 -&gt; 5</code>, que tem uma distância de <strong>22</strong> para o nó de origem (2 + 5 + 15). Essa distância já foi registrada na lista de distâncias em uma etapa anterior.</li><li>A segunda opção seria seguir o caminho <code>0 -&gt; 1 -&gt; 3 -&gt; 4 -&gt; 5</code>, que tem uma distância de <strong>23</strong> para o nó de origem (2 + 5 + 10 + 6).</li></ul><p>Claramente, o primeiro caminho é mais curto, então o escolhemos para nó <code>5</code>.</p><p><strong>No caso do nó <code>6</code>:</strong></p><ul><li>O caminho disponível é <code>0 -&gt; 1 -&gt; 3 -&gt; 4 -&gt; 6</code>, que tem uma distância de <strong>19</strong> para o nó de origem (2 + 5 + 10 + 2).</li></ul><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-110.png" class="kg-image" alt="image-110" width="435" height="293" loading="lazy"></figure><p>Marcamos o nó com a distância mais curta (atualmente conhecida) como visitada. Neste caso, o nó<code>6</code>.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-110-1.png" class="kg-image" alt="image-110-1" width="435" height="293" loading="lazy"></figure><p>E o riscamos da lista de nós não visitados:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-111.png" class="kg-image" alt="image-111" width="585" height="65" loading="lazy"></figure><p>Agora temos este caminho (marcado em vermelho):</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-112--1-.png" class="kg-image" alt="image-112--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-112--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-112--1-.png 886w" width="886" height="393" loading="lazy"></figure><p>Apenas um nó ainda não foi visitado, o nó <code>5</code>. Vamos ver como podemos incluí-lo no caminho.</p><p>Existem três caminhos diferentes que podemos seguir para alcançar o nó <code>5</code>a partir dos nós que foram adicionados ao caminho:</p><ul><li><strong>Opção 1: </strong><code>0 -&gt; 1 -&gt; 3 -&gt; 5</code> com uma distância de <strong>22 </strong> (2 + 5 + 15).</li><li><strong>Opção 2: </strong><code>0 -&gt; 1 -&gt; 3 -&gt; 4 -&gt; 5</code> com uma distância de <strong>23</strong> (2 + 5 + 10 + 6).</li><li><strong>Opção 3:</strong> <code>0 -&gt; 1 -&gt; 3 -&gt; 4 -&gt; 6 -&gt; 5</code> com uma distância de <strong>25 </strong>(2 + 5 + 10 + 2 + 6).</li></ul><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-113.png" class="kg-image" alt="image-113" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-113.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/03/image-113.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-113.png 1006w" sizes="(min-width: 720px) 720px" width="1006" height="295" loading="lazy"></figure><p>Selecionamos o caminho: <code>0 -&gt; 1 -&gt; 3 -&gt; 5</code> com uma distância de <strong>22</strong>.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-115.png" class="kg-image" alt="image-115" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-115.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-115.png 856w" width="856" height="394" loading="lazy"></figure><p>Marcamos o nó como visitado e o riscamos da lista de nós não visitados:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-114.png" class="kg-image" alt="image-114" width="210" height="301" loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-116.png" class="kg-image" alt="image-116" width="593" height="68" loading="lazy"></figure><p><strong>E aí está!</strong> Temos o resultado final com o caminho mais curto do nó <code>0</code> até cada nó do grafo.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-115--1-.png" class="kg-image" alt="image-115--1-" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/03/image-115--1-.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/03/image-115--1-.png 856w" width="856" height="394" loading="lazy"></figure><p>No diagrama, as linhas vermelhas marcam as arestas que pertencem ao caminho mais curto. Você precisa seguir essas arestas para seguir o caminho mais curto para chegar a um determinado nó no grafo a partir do nó <code>0</code>.</p><p>Por exemplo, se você deseja alcançar o nó <code>6</code> a partir do nó <code>0</code>, basta seguir as arestas vermelhas e estará, automaticamente, seguindo o caminho mais curto <code>0 -&gt; 1 -&gt; 3 -&gt; 4 - &gt; 6</code>.</p><h2 id="-resumindo">🔸 Resumindo</h2><ul><li>Os grafos são usados para modelar conexões entre objetos, pessoas ou entidades. Eles têm dois elementos principais: nós e arestas. Os nós representam objetos e as arestas representam as conexões entre esses objetos.</li><li>O algoritmo de Dijkstra encontra o caminho mais curto entre um determinado nó (que é chamado de "nó de origem") e todos os outros nós em um grafo.</li><li>Este algoritmo usa os pesos das arestas para encontrar o caminho que minimiza a distância total (peso) entre o nó de origem e todos os outros nós.</li></ul><p><strong>Eu realmente espero que você tenha gostado do artigo e o tenha achado útil</strong>. Agora, você sabe como o algoritmo de Dijkstra funciona nos bastidores. Siga a autora no Twitter (<a href="https://twitter.com/EstefaniaCassN">@EstefaniaCassN</a>) e <a href="https://www.udemy.com/user/estefania-cn/">confira os cursos da autora on-line</a>.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Roteiro de aprendizagem de Ciência de Dados ]]>
                </title>
                <description>
                    <![CDATA[ Embora nada realmente mude, exceto a data, um novo ano deixa todos nós com a esperança de começar de novo. Se você adicionar um pouco de planejamento, algumas metas bem planejadas e um roteiro de aprendizagem, terá uma ótima receita para um ano cheio de crescimento. Esta postagem pretende fortalecer ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/roteiro-de-aprendizagem-de-ciencia-de-dados/</link>
                <guid isPermaLink="false">6207eb11cfef2204db7edf58</guid>
                
                    <category>
                        <![CDATA[ Ciência de dados ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Cayo Dias ]]>
                </dc:creator>
                <pubDate>Fri, 25 Feb 2022 18:28:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/Blue-and-Ivory-Photo-Musician-Influencer-Digital-Brutalism-YouTube-Thumbnail-Set.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/data-science-learning-roadmap/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Data Science Learning Roadmap</a>
      </p><p>Embora nada realmente mude, exceto a data, um novo ano deixa todos nós com a esperança de começar de novo. Se você adicionar um pouco de planejamento, algumas metas bem planejadas e um roteiro de aprendizagem, terá uma ótima receita para um ano cheio de crescimento.</p><p>Esta postagem pretende fortalecer seu plano, <strong>fornecendo uma estrutura de aprendizagem, recursos e ideias de projetos</strong> para ajudá-lo a construir um portfólio sólido de trabalho apresentando experiência em ciência de dados.</p><p>Apenas uma observação: preparei este roteiro com base na minha experiência pessoal em ciência de dados. Este não é o plano de aprendizagem definitivo. Você pode adaptar este roteiro para melhor se adequar a qualquer domínio ou campo de estudo específico que lhe interesse. Além disso, ele foi criado com o Python em mente, pois eu pessoalmente prefiro essa linguagem.</p><h2 id="o-que-um-roteiro-de-aprendizagem">O que é um roteiro de aprendizagem?</h2><p>Um roteiro de aprendizagem é uma extensão de um programa de estudos. Ele traça um mapa de habilidades de vários níveis com detalhes sobre <strong>quais</strong> habilidades você deseja aprimorar, <strong>como </strong>você medirá o resultado em cada nível e <strong>técnicas</strong> para dominar ainda mais cada habilidade.</p><p>Meu roteiro atribui pesos a cada nível com base na complexidade e semelhança de sua aplicação no mundo real. Eu também adicionei um tempo estimado para um iniciante completar cada nível com exercícios e projetos.</p><p>Aqui está uma pirâmide que descreve as habilidades de alto nível em ordem de complexidade e aplicação no setor.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/IMG-0021.jpg" class="kg-image" alt="IMG-0021" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/IMG-0021.jpg 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/IMG-0021.jpg 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/02/IMG-0021.jpg 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/IMG-0021.jpg 2000w" sizes="(min-width: 720px) 720px" width="2000" height="1340" loading="lazy"><figcaption>Atividades de Ciência de Dados em ordem de complexidade</figcaption></figure><p>Ela marcará a base de nossa estrutura. Agora teremos que nos aprofundar em cada um desses estratos para completar nossa estrutura com detalhes mais específicos e mensuráveis.</p><p>A especificidade vem do exame dos tópicos críticos em cada camada e dos recursos necessários para dominar esses tópicos.</p><p>Podemos medir o conhecimento adquirido, aplicando os tópicos aprendidos a vários projetos do mundo real. Adicionei algumas ideias de projetos, portais e plataformas que você pode usar para medir sua proficiência.</p><blockquote>NOTA importante: viva um dia de cada vez, um vídeo/blog/capítulo por dia. É um amplo espectro para se cobrir. Não se sobrecarregue!</blockquote><p>Vamos mergulhar profundamente em cada um desses estratos, começando pela base.</p><h2 id="1-como-aprender-sobre-programa-o-ou-engenharia-de-software">1. Como aprender sobre programação ou engenharia de software</h2><p><strong>(Tempo estimado: 2-3 meses)</strong></p><p>Primeiro, certifique-se de ter boas habilidades de programação. Toda descrição de trabalho de ciência de dados exigirá experiência em programação em pelo menos uma linguagem.</p><h3 id="t-picos-espec-ficos-de-programa-o-a-serem-conhecidos-incluem-">Tópicos específicos de programação a serem conhecidos incluem:</h3><ul><li>Estruturas de dados comuns (tipos de dados, listas, dicionários, conjuntos, tuplas), funções, lógica, controle de fluxo, algoritmos de busca e ordenação, programação orientada a objetos e trabalho com bibliotecas externas</li><li>Scripts de SQL: consultas a bancos de dados usando JOIN, funções de agregação e subconsultas</li><li>Tranquilidade no uso do Terminal, controle de versão usando Git e GitHub</li></ul><h3 id="recursos-para-aprender-python-">Recursos para aprender Python:</h3><ul><li><a href="https://www.learnpython.org/" rel="noopener">learnpython.org</a> [gratuito]— um recurso gratuito para iniciantes. Abrange todos os tópicos básicos de programação desde o básico. Você dispõe de um shell interativo para praticar esses tópicos lado a lado.</li><li><a href="https://www.kaggle.com/learn/python" rel="noopener">Kaggle</a> [gratuito]— um guia gratuito e interativo para aprender Python. É um tutorial curto que cobre todos os tópicos importantes para a ciência de dados.</li><li>Certificações de <a href="https://www.freecodecamp.org/learn/scientific-computing-with-python/python-for-everybody/">Python no freeCodeCamp</a> [gratuito] – o freeCodeCamp oferece diversas certificações baseadas em Python, como computação científica, análise de dados e aprendizagem de máquina.</li><li>Curso de <a href="https://www.youtube.com/watch?v=rfscVS0vtbw" rel="noopener">Python no canal do freeCodeCamp no YouTube</a> [gratuito] — Este é um curso de 5 horas que você pode fazer para praticar os conceitos básicos.</li><li><a href="https://www.youtube.com/watch?v=HGOBQPFzWKo" rel="noopener">Python intermediário </a>[gratuito]— Outro curso gratuito apresentado no freecodecamp.org pelo Patrick.</li><li><a href="https://www.coursera.org/specializations/python" rel="noopener">Python for Everybody Specialization</a> (Especialização em Python para todos) no <a href="https://www.coursera.org/specializations/python" rel="noopener">Coursera</a> [pago] — esta é uma especialização que abrange conceitos de nível iniciante, estruturas de dados em Python, coleta de dados da web e uso de bancos de dados com Python.</li></ul><h3 id="recursos-para-aprender-git-e-github">Recursos para aprender Git e GitHub</h3><ul><li>Guia <a href="https://www.atlassian.com/git" rel="noopener">para Git</a> e <a href="https://lab.github.com/" rel="noopener">GitHub</a> [gratuito]: complete esses tutoriais e laboratórios para ter uma ideia sólida de controle de versão. Esses cursos o ajudarão a contribuir ainda mais para projetos de código aberto.</li><li>Aqui temos um <a href="https://www.freecodecamp.org/news/git-and-github-crash-course/">curso intensivo sobre Git e GitHub</a> no canal do freeCodeCamp no YouTube.</li></ul><h3 id="recursos-para-aprender-sql">Recursos para aprender SQL</h3><ul><li>Aqui, temos um <a href="https://www.freecodecamp.org/news/sql-and-databases-full-course/">curso sobre SQL e bancos de dados</a> no canal do freeCodeCamp no YouTube</li><li><a href="https://www.kaggle.com/learn/intro-to-sql" rel="noopener">Introdução ao SQL</a> e <a href="https://www.kaggle.com/learn/advanced-sql">SQL avançado</a> no Kaggle.</li><li>Treehouse oferece um <a href="https://teamtreehouse.com/tracks/beginning-sql">bom curso introdutório sobre SQL aqui</a>.</li></ul><h3 id="me-a-sua-experi-ncia-resolvendo-muitos-problemas-e-construindo-pelo-menos-2-projetos-">Meça sua experiência resolvendo muitos problemas e construindo pelo menos 2 projetos:</h3><ul><li>Resolva muitos problemas em: <a href="https://www.hackerrank.com/" rel="noopener nofollow noopener">HackerRank</a> (recomendado para iniciantes) e <a href="https://leetcode.com/" rel="noopener nofollow noopener">LeetCode</a> (resolva questões fáceis ou de nível médio)</li><li>Extração de dados de um site/endpoints  de APIs — tente escrever scripts em Python para extrair dados de páginas da web que permitem scraping (raspagem da web) como o soundcloud.com. Armazene os dados extraídos em um arquivo CSV ou em um banco de dados SQL.</li><li>Jogos como pedra-papel-tesoura, girar o novelo, forca, simulador de rolagem de dados, jogo da velha e assim por diante.</li><li>Aplicativos web simples, como um programa para baixar vídeos do YouTube, bloqueador de sites, reprodutor de música, verificador de plágio e assim por diante.</li></ul><p>Hospede esses projetos em páginas do GitHub Pages ou simplesmente mantenha os códigos no GitHub para que você aprenda a usar o Git.</p><h2 id="2-como-aprender-sobre-coleta-de-dados-e-data-wrangling-limpeza-manipula-o-">2. Como aprender sobre coleta de dados e &nbsp;"data wrangling" (limpeza/manipulação)</h2><p>(Tempo estimado: 2 meses)</p><p>Uma parte significativa do trabalho de ciência de dados está centrada em encontrar dados adequados que possam ajudá-lo a resolver seu problema. Você pode coletar dados de diferentes fontes legítimas — scraping (raspagem - se o site permitir), APIs, bancos de dados e repositórios disponíveis publicamente.</p><p>Uma vez que você tenha os dados em mãos, como um analista, frequentemente, você se encontrará limpando dataframes, trabalhando com arrays multidimensionais, usando cálculos descritivos/científicos e manipulando dataframes para agregar dados.</p><p>No mundo real, raramente, os dados são encontrados limpos, formatados e prontos para uso. Pandas e NumPy são as duas bibliotecas que estão à sua disposição para transformar dados brutos em dados prontos para análise.</p><p>À medida que você começar a se sentir confortável escrevendo programas em Python, sinta-se à vontade para começar a ter aulas sobre o uso de bibliotecas como <strong>pandas</strong> e <a href="https://towardsdatascience.com/numpy-essentials-for-data-science-25dc39fae39" rel="noopener"><strong>numpy</strong></a>.</p><h3 id="recursos-para-aprender-sobre-coleta-e-limpeza-de-dados-">Recursos para aprender sobre coleta e limpeza de dados:</h3><ul><li><a href="https://www.youtube.com/watch?v=r-uOLxNrNk8" rel="noopener">Curso sobre Numpy, Pandas, matplotlib e seaborn no freeCodeCamp</a> [gratuito].</li><li>Tutorial prático da HackerEarth sobre <a href="https://www.hackerearth.com/practice/machine-learning/data-manipulation-visualisation-r-python/tutorial-data-manipulation-numpy-pandas-python/tutorial/">manipulação de dados com NumPy e Pandas, usando o Python</a>.</li><li><a href="https://www.kaggle.com/learn/pandas" rel="noopener">Tutorial sobre pandas da Kaggle</a> [gratuito] — um tutorial prático curto e conciso que o guiará pelas habilidades mais comuns de manipulação de dados.</li><li><a href="https://www.kaggle.com/learn/data-cleaning" rel="noopener">Curso de limpeza de dados da Kaggle</a>.</li><li><a href="https://www.coursera.org/learn/python-data-analysis?specialization=data-science-python" rel="noopener">Curso de Introdução à Ciência de Dados usando Python do Coursera</a>  — este é o primeiro curso da <a href="https://www.coursera.org/specializations/data-science-python" rel="noopener">Especialização em Ciência de Dados com Python.</a></li></ul><h3 id="ideias-de-projetos-de-coleta-de-dados-">Ideias de projetos de coleta de dados:</h3><ul><li>Colete dados de um site/API (aberto para consumo público) de sua escolha e transforme os dados para armazená-los de diferentes fontes em um arquivo ou tabela agregada (DB). Exemplos de APIs incluem: <a href="https://developers.themoviedb.org/3" rel="noopener">TMDB</a>, <a href="https://www.quandl.com/tools/python" rel="noopener">quandl</a>, <a href="https://developer.twitter.com/en/docs" rel="noopener">Twitter API</a>, e assim por diante.</li><li>Escolha<a href="https://towardsdatascience.com/data-repositories-for-almost-every-type-of-data-science-project-7aa2f98128b" rel="noopener"> qualquer conjunto de dados disponível publicamente</a> e defina um conjunto de perguntas que você gostaria de responder depois de analisar o conjunto de dados e o domínio. Manipule os dados para encontrar respostas para essas perguntas usando Pandas e NumPy.</li></ul><h2 id="3-como-aprender-sobre-an-lise-explorat-ria-de-dados-business-acumen-and-storytelling">3. Como aprender sobre análise exploratória de dados, Business Acumen, and Storytelling</h2><p>(Tempo estimado: 2–3 meses)</p><p>A próxima etapa a ser dominada compreende a análise de dados e o storytelling (contar a história, em inglês). Extrair insights dos dados e, em seguida, comunicá-los aos gestores, fazendo uso de expressões simples e visualizações é a principal responsabilidade de um analista de dados.</p><p>A parte do storytelling exige que você seja proficiente em visualização de dados, além de possuir excelentes habilidades de comunicação.</p><h3 id="t-picos-espec-ficos-de-an-lise-de-dados-explorat-rios-e-storytelling-para-aprender-incluem-">Tópicos específicos de análise de dados exploratórios e storytelling para aprender incluem:</h3><ul><li>Análise de dados exploratória — definição de perguntas, tratamento de dados faltantes, pontos fora da curva (também conhecidos pela palavra em inglês, <em>outliers</em>), formatação, filtragem, análises univariada e multivariada.</li><li>Visualização de dados — construção de gráficos, usando bibliotecas como matplotlib, seaborn e plotly. Saber como escolher o gráfico certo para comunicar as conclusões obtidas a partir dos dados.</li><li>Desenvolvimento de dashboards — uma boa porcentagem de analistas usa apenas o Excel ou uma ferramenta especializada como Power BI e Tableau para criar dashboards que resumem/agregam dados para ajudar os gestores a tomar decisões.</li><li>Conhecimento de negócios: faça as perguntas certas e responda as que são realmente relacionadas às métricas de negócios. Pratique a redação de relatórios, blogs e apresentações claras e concisas.</li></ul><h3 id="recursos-para-aprender-mais-sobre-an-lise-de-dados-">Recursos para aprender mais sobre análise de dados:</h3><ul><li>Aprenda análise de dados com Python neste <a href="https://www.freecodecamp.org/news/learn-data-analysis-with-python-course/">curso gratuito no canal do freeCodeCamp no YouTube</a>.</li><li><a href="https://www.coursera.org/learn/data-analysis-with-python" rel="noopener">Análise de dados com Python</a> — da IBM no Coursera. O curso abrange data wrangling, análise exploratória e desenvolvimento de modelos simples usando Python.</li><li><a href="https://www.kaggle.com/learn/data-visualization" rel="noopener">Visualização de dados</a> — Kaggle. Outro curso interativo que permite praticar a construção de gráficos comumente utilizados.</li><li>Desenvolva senso de produto e business acumen com estes livro: <a href="https://www.amazon.com/Measure-What-Matters-Google-Foundation/dp/0525536221/ref=sr_1_1?crid=1A9SIXXP7S2P8&amp;dchild=1&amp;keywords=measure+what+matters&amp;qid=1610323490&amp;s=books&amp;sprefix=measure%2Cstripbooks%2C365&amp;sr=1-1" rel="noopener">Measure what matters</a><strong> </strong>(<a href="https://www.amazon.com.br/Avalie-que-Importa-Funda%C3%A7%C3%A3o-Sacudiram/dp/855080455X/ref=sr_1_2?keywords=measure+what+matters&amp;qid=1645285940&amp;sprefix=measure+what+%2Caps%2C328&amp;sr=8-2">Avalie o que importa</a>)<strong>, </strong><a href="https://www.amazon.com/Decode-Conquer-Answers-Management-Interviews/dp/0615930417/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1530848101&amp;sr=1-1&amp;keywords=decode+and+conquer" rel="noopener nofollow noopener noopener">Decode and conquer</a> (<a href="https://www.amazon.com.br/Decodificar-Conquistar-Respostas-entrevistas-gerenciamento/dp/0998120499/ref=sr_1_3?__mk_pt_BR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;crid=UI5K95ZHR5S6&amp;keywords=Cracking+the+PM+interview&amp;qid=1645285910&amp;sprefix=cracking+the+pm+interview%2Caps%2C226&amp;sr=8-3&amp;ufe=app_do%3Aamzn1.fos.25548f35-0de7-44b3-b28e-0f56f3f96147">Decodificar e Conquistar</a>), <a href="https://www.amazon.com/Cracking-PM-Interview-Product-Technology/dp/0984782818/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1530848116&amp;sr=1-1&amp;keywords=cracking+the+pm+interview" rel="noopener nofollow noopener">Cracking the PM interview</a><strong>.</strong></li></ul><h3 id="ideias-de-projetos-de-an-lise-de-dados">Ideias de projetos de análise de dados</h3><ul><li>Análise exploratória de <a href="https://towardsdatascience.com/hitchhikers-guide-to-exploratory-data-analysis-6e8d896d3f7e" rel="noopener">bancos de dados de filmes para encontrar a fórmula para criar filmes lucrativos</a> (use como inspiração). Use conjuntos de dados de saúde, finanças, OMS, censos anteriores, comércio eletrônico e assim por diante.</li><li>Construa dashboards (jupyter notebooks, excel, <a href="https://public.tableau.com/en-gb/gallery/?tab=viz-of-the-day&amp;type=viz-of-the-day" rel="noopener">tableau</a>) usando os recursos fornecidos acima.</li></ul><h2 id="4-como-aprender-sobre-engenharia-de-dados">4. Como aprender sobre engenharia de dados</h2><p>(Tempo estimado: 4–5 meses)</p><p>A engenharia de dados sustenta as equipes de Pesquisa e Desenvolvimento, tornando os dados limpos acessíveis a engenheiros de pesquisa e cientistas em empresas orientadas a big data. É um campo por si só, e você pode pular esta seção se quiser se concentrar apenas na parte dos algoritmos estatísticos.</p><p>As responsabilidades de um engenheiro de dados incluem construir uma arquitetura de dados eficiente, simplificar o processamento de dados e manter sistemas de dados em grande escala.</p><p>Engenheiros de dados usam o Shell (interface de linha de comando – CLI), SQL e Python/Scala para criar pipelines de extração, transformação e carga de dados (ETL, do inglês Extract, Transform and Load), automatizar tarefas do sistema de arquivos e otimizar as operações do banco de dados para torná-las de alto desempenho.</p><p>Outra habilidade essencial é implementar essas arquiteturas de dados que exigem proficiência em provedores de serviços em nuvem como AWS, Google Cloud Platform, Microsoft Azure e outros.</p><h3 id="recursos-para-aprender-engenharia-de-dados-">Recursos para aprender engenharia de dados:</h3><ul><li><a href="https://www.udacity.com/course/data-engineer-nanodegree--nd027" rel="noopener">Data Engineering Nanodegree da Udacity </a>— no que diz respeito a uma lista compilada de recursos, não encontrei um curso mais bem estruturado sobre engenharia de dados que cubra todos os principais conceitos do zero.</li><li><a href="https://www.coursera.org/specializations/gcp-data-machine-learning" rel="noopener">Especialização em Engenharia de Dados, Big Data e Aprendizagem de Máquina na GCP</a> — Você pode concluir esta especialização oferecida pelo Google no Coursera, que orienta você por todas as principais APIs e serviços oferecidos pela GCP (Google Cloud Platform) para criar uma solução de dados completa.</li></ul><h3 id="ideias-de-projetos-prepara-o-para-certifica-es-em-engenharia-de-dados-">Ideias de projetos/preparação para certificações em engenharia de dados:</h3><ul><li><a href="https://aws.amazon.com/certification/certified-machine-learning-specialty/" rel="noopener">AWS Certified Machine Learning (US$ 300) </a>— um exame supervisionado oferecido pela AWS adiciona algum peso ao seu perfil (embora não garanta nada), requer uma compreensão razoável dos serviços da AWS e ML.</li><li><a href="https://cloud.google.com/certification/data-engineer" rel="noopener">Professional Data Engineer</a> — este também é um exame supervisionado e avalia suas habilidades para projetar sistemas de processamento de dados, implantar modelos de aprendizagem de máquina em um ambiente de produção e garantir a qualidade e a automação das soluções.</li></ul><h2 id="5-como-aprender-sobre-estat-stica-aplicada-e-matem-tica">5. Como aprender sobre Estatística Aplicada e Matemática</h2><p>(Tempo estimado: 4–5 meses)</p><p>Os métodos estatísticos são uma parte central da ciência de dados. Quase todas as entrevistas de ciência de dados se concentram predominantemente em estatísticas descritivas e inferenciais.</p><p>As pessoas geralmente começam a programar algoritmos de aprendizagem de máquina sem uma compreensão clara dos métodos estatísticos e matemáticos subjacentes que explicam o funcionamento desses algoritmos. Esta, claro, não é a melhor maneira de fazer isso.</p><h3 id="t-picos-em-que-voc-deve-se-concentrar-em-estat-stica-aplicada-e-matem-tica-">Tópicos em que você deve se concentrar em Estatística Aplicada e Matemática:</h3><ul><li><strong>Estatística Descritiva</strong> — ser capaz de resumir os dados é uma habilidade poderosa, mas nem sempre. Aprenda sobre medidas de posição (média, mediana, moda, estatísticas ponderadas, estatísticas truncadas) e variabilidade para descrever os dados.</li><li><strong>Estatística Inferencial </strong>— projetar testes de hipóteses, testes A/B, definir métricas de negócios, analisar os dados coletados e resultados de experimentos usando intervalo de confiança, valor p e valores alfa.</li><li><strong>Álgebra Linear, Cálculo uni e multivariado</strong> para entender as funções de custo, gradiente e otimizadores em aprendizagem de máquina.</li></ul><h3 id="recursos-para-aprender-sobre-estat-stica-e-matem-tica-">Recursos para aprender sobre Estatística e Matemática:</h3><ul><li><a href="https://www.freecodecamp.org/news/free-statistics-course/">Aprenda Estatística de nível universitário</a> neste curso gratuito de 8 horas no canal do freeCodeCamp no YouTube</li><li><a href="https://www.amazon.com/Practical-Statistics-Data-Scientists-Essential/dp/149207294X/ref=sr_1_1?crid=QOOZP96ISCU4&amp;dchild=1&amp;keywords=practical+statistics+for+data+scientists&amp;qid=1610247485&amp;s=books&amp;sprefix=practical+stat%2Cstripbooks%2C362&amp;sr=1-1" rel="noopener">[Livro] </a><a href="https://www.amazon.com.br/Estat%C3%ADstica-Pr%C3%A1tica-Para-Cientistas-Dados/dp/855080603X/ref=sr_1_3?__mk_pt_BR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;crid=1FZT36S1ZA4TJ&amp;keywords=Practical+Statistics+for+Data+Scientists&amp;qid=1645393791&amp;sprefix=practical+statistics+for+data+scientists%2Caps%2C210&amp;sr=8-3">Estatística prática para cientistas de dados</a> <strong>(altamente recomendado) — </strong>um guia completo sobre todos os métodos estatísticos importantes, juntamente com aplicações/exemplos claros e concisos.</li><li><a href="https://www.amazon.com/Naked-Statistics-Stripping-Dread-Data/dp/1480590185" rel="noopener">[Livro] Naked Statistics </a>— um guia não técnico, mas detalhado, para entender o impacto das estatísticas em nossos eventos de rotina, esportes, sistemas de recomendação e muitos outros casos.</li><li><a href="https://learn.datacamp.com/courses/statistical-thinking-in-python-part-1" rel="noopener">Statistical thinking in Python</a> — um curso básico para ajudá-lo a começar a pensar estatisticamente. Há uma segunda parte para este curso também.</li><li><a href="https://www.udacity.com/course/intro-to-descriptive-statistics--ud827" rel="noopener">Intro to Descriptive Statistics</a>— oferecido pela Udacity. Consiste em aulas em vídeo, explicando medidas amplamente utilizadas de posição e variabilidade (desvio padrão, variância, desvio médio absoluto).</li><li><a href="https://www.udacity.com/course/intro-to-inferential-statistics--ud201" rel="noopener">Inferential Statistics, Udacity </a>— o curso consiste em aulas em vídeo que ensinam você a tirar conclusões a partir de dados que podem não ser imediatamente óbvios. Ele se concentra no desenvolvimento de hipóteses e usa testes comuns, como teste t, ANOVA e regressão.</li><li>E aqui está um <a href="https://www.freecodecamp.org/news/statistics-for-data-science/">guia de Estatística para Ciência de Dados</a> para ajudá-lo a começar no caminho certo.</li></ul><h3 id="ideias-de-projetos-de-estat-stica-">Ideias de projetos de Estatística:</h3><ul><li>Resolva os exercícios fornecidos nos cursos acima e tente passar por vários conjuntos de dados públicos onde você pode aplicar esses conceitos estatísticos. Faça perguntas como “Existem evidências suficientes para concluir que a idade média das mães que dão à luz em Boston é superior a 25 anos no nível de significância de 0,05”?</li><li>Tente projetar e executar pequenos experimentos com seus colegas/grupos/turmas, pedindo que eles interajam com um aplicativo ou respondam a uma pergunta. Execute métodos estatísticos nos dados coletados quando tiver uma boa quantidade de dados após um período de tempo. Isso pode ser muito difícil de conseguir, mas deve ser muito interessante.</li><li>Analise os preços das ações, criptomoedas e hipóteses de design em torno do retorno médio ou qualquer outra métrica. Determine se você pode rejeitar a hipótese nula ou deixar de fazê-lo usando valores críticos.</li></ul><h2 id="6-como-aprender-sobre-aprendizagem-de-m-quina-e-ia">6. Como aprender sobre aprendizagem de máquina e IA</h2><p>(Tempo estimado: 4–5 meses)</p><p>Depois de se questionar e passar por todos os principais conceitos mencionados acima, agora você deve estar pronto para começar com os sofisticados algoritmos de ML (Machine Learning - Aprendizagem de Máquina).</p><p>Há três tipos principais de aprendizagem:</p><ol><li><strong>Aprendizagem supervisionada</strong> — inclui problemas de regressão e classificação. Estude regressão linear simples, regressão múltipla, regressão polinomial, Naive Bayes, regressão logística, KNNs, árvores de classificação, modelos ensemble. Saiba mais sobre as métricas de avaliação.</li><li><strong>Aprendizagem não supervisionada</strong>— agrupamento e redução de dimensionalidade são as duas aplicações amplamente utilizadas de aprendizagem não supervisionada. Mergulhe profundamente em PCA, agrupamento K-means, agrupamento hierárquico e misturas gaussianas.</li><li><strong>Aprendizagem por reforço </strong>(não obrigatório*) — ajuda você a construir sistemas de autorrecompensa. Aprenda a otimizar recompensas, usando a biblioteca TF-Agents, criando Q-networks profundas e assim por diante.</li></ol><p>A maioria dos projetos de ML precisa que você domine várias tarefas explicadas <a href="https://towardsdatascience.com/task-cheatsheet-for-almost-every-machine-learning-project-d0946861c6d0" rel="noopener">neste artigo</a>.</p><h3 id="recursos-para-aprender-sobre-aprendizagem-de-m-quina-">Recursos para aprender sobre Aprendizagem de Máquina:</h3><ul><li>Aqui temos um curso completo &nbsp;de <a href="https://www.freecodecamp.org/news/machine-learning-with-scikit-learn-full-course/">Aprendizagem de máquina usando Python e a biblioteca SciKitLearn</a> no canal do freeCodeCamp no YouTube.</li><li>[Livro] <a href="https://www.amazon.com/Hands-Machine-Learning-Scikit-Learn-TensorFlow/dp/1492032646/ref=sr_1_1?dchild=1&amp;keywords=Hands-On+Machine+Learning+with+Scikit-Learn%2C+Keras%2C+and+TensorFlow%2C+2nd+Edition&amp;qid=1610253356&amp;sr=8-1" rel="noopener">Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow, 2nd Edition</a> — um dos meus livros favoritos de todos os tempos sobre aprendizagem de máquina. Não cobre apenas as derivações matemáticas teóricas, mas também mostra a implementação de algoritmos através de exemplos. Você deve resolver os exercícios dados no final de cada capítulo.</li><li><a href="https://www.coursera.org/learn/machine-learning" rel="noopener">Curso de Aprendizagem de Máquina por Andrew Ng</a> — curso obrigatório para quem está tentando aprender machine learning. Definitivamente!</li><li><a href="https://www.kaggle.com/learn/intro-to-machine-learning" rel="noopener">Introduction to Machine Learning</a> — Curso interativo no Kaggle.</li><li><a href="https://www.kaggle.com/learn/intro-to-game-ai-and-reinforcement-learning" rel="noopener">Intro to Game AI and Reinforcement Learning</a> — outro curso interativo no Kaggle sobre aprendizagem por reforço.</li></ul><h3 id="especializa-o-em-deep-learning-na-deeplearning-ai"><a href="https://www.deeplearning.ai/deep-learning-specialization/" rel="noopener">Especialização em Deep Learning na deeplearning.ai</a></h3><p>Para aqueles que estão interessados em mergulhar ainda mais em Deep Learning, você pode começar concluindo esta especialização oferecida pela deeplearning.ai e o livro <a href="https://www.amazon.com/Hands-Machine-Learning-Scikit-Learn-TensorFlow/dp/1492032646/ref=sr_1_1?dchild=1&amp;keywords=Hands-On+Machine+Learning+with+Scikit-Learn%2C+Keras%2C+and+TensorFlow%2C+2nd+Edition&amp;qid=1610253356&amp;sr=8-1">Hands-On</a>. Isso não é tão importante do ponto de vista da ciência de dados, a menos que você esteja planejando resolver um problema de visão computacional ou NLP (do inglês Natural Language Processing - processamento de linguagens naturais).</p><p>Deep Learning merece um roteiro dedicado. Vou criar um com todos os conceitos fundamentais em breve.</p><h2 id="acompanhe-seu-progresso-de-aprendizagem">Acompanhe seu progresso de aprendizagem</h2><p>Também criei uma página no Notion onde você poderá acompanhar sua aprendizagem. Você pode personalizá-la de acordo com suas necessidades e usá-la para acompanhar seu progresso, ter acesso fácil a todos os recursos e seus projetos.</p><p><a href="https://www.notion.so/Data-Science-learning-tracker-0d3c503280d744acb1b862a1ddd8344e">Aqui está o link</a>.</p><p>Além disso, aqui está a versão em vídeo deste artigo:</p><h3 id="ci-ncia-de-dados-com-harshit"><a href="https://www.youtube.com/c/DataSciencewithHarshit?sub_confirmation=1" rel="noopener nofollow noopener">Ciência de dados com Harshit</a></h3><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.17977528089888%;" class="fluid-width-video-wrapper">
            <iframe width="356" height="200" src="https://www.youtube.com/embed/nM_wZIzKEhc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" name="fitvid0"></iframe>
          </div>
        </div>
      </figure><p>Esta é apenas uma visão geral de alto nível do amplo espectro da ciência de dados. Você pode querer se aprofundar em cada um desses tópicos e criar um plano de menor rigor baseado em conceitos para cada uma das categorias.</p><p>Se este tutorial foi útil para você, confira os cursos do autor sobre Ciência de Dados e Aprendizagem de Máquina na <a href="https://www.wiplane.com/">Wiplane Academy</a>. Eles são abrangentes, mas compactos, e ajudam você a construir uma base sólida de trabalho para mostrar.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como criar e manipular bancos de dados SQL com Python ]]>
                </title>
                <description>
                    <![CDATA[ Python [https://docs.python.org/pt-br/3/] e SQL [https://pt.wikipedia.org/wiki/SQL] são duas das linguagens mais importantes para analistas de dados. Neste artigo, mostrarei tudo que você precisa saber para conectar o Python e o SQL. Você aprenderá a obter dados de bancos de dados relacionais diretamente de seus pipelines de aprendizado de máquina, armazenar dados ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-criar-e-manipular-bancos-de-dados-sql-com-python/</link>
                <guid isPermaLink="false">61ed7ef7b5028e04fdf66700</guid>
                
                    <category>
                        <![CDATA[ SQL ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Cayo Dias ]]>
                </dc:creator>
                <pubDate>Sat, 19 Feb 2022 15:32:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/Untitled-design-1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/connect-python-with-sql/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Create and Manipulate SQL Databases with Python</a>
      </p><p><a href="https://docs.python.org/pt-br/3/">Python</a> e <a href="https://pt.wikipedia.org/wiki/SQL">SQL</a> são duas das linguagens mais importantes para analistas de dados.</p><p>Neste artigo, mostrarei tudo que você precisa saber para conectar o Python e o SQL.</p><p>Você aprenderá a obter dados de bancos de dados relacionais diretamente de seus pipelines de aprendizado de máquina, armazenar dados de suas aplicações em Python em um banco de dados próprio ou qualquer outro caso de uso que possa surgir.</p><p>Juntos, vamos aprender:</p><ul><li>Por que aprender a usar Python e SQL juntos?</li><li>Como configurar seu ambiente Python e MySQL Server</li><li>Conectar ao MySQL Server usando Python</li><li>Criar um novo banco de dados</li><li>Criar tabelas e relacionamentos entre elas</li><li>Preencher as tabelas com dados</li><li>Ler dados</li><li>Atualizar registros</li><li>Apagar registros</li><li>Criar registros a partir de listas do Python</li><li>Criar funções reutilizáveis para fazer tudo isso por nós no futuro</li></ul><p>São muitas coisas úteis e interessantes. Vamos começar!</p><p>Um breve comentário antes de começarmos: um Jupyter Notebook com todos os códigos usados neste tutorial está disponível neste <a href="https://github.com/thecraigd/Python_SQL">repositório do GitHub</a>. Reproduzir os códigos enquanto lê este artigo é altamente recomendado!</p><p>O banco de dados e os códigos SQL usados aqui são todos provenientes da minha série <a href="https://towardsdatascience.com/tagged/sql-series">Introduction to SQL </a>(Introdução ao SQL) publicada (em inglês) no site <a href="https://towardsdatascience.com/">Towards Data Science</a> (<a href="https://www.craigdoesdata.de/contact.html">entre em contato</a> se tiver algum problema para visualizar os artigos e eu enviarei um link para que eles possam ser acessados gratuitamente).</p><p>Se não está acostumado com SQL e com os conceitos subjacentes aos bancos de dados relacionais, eu indicaria <a href="https://towardsdatascience.com/tagged/sql-series">essa série</a> (além disso, é claro que há uma enorme quantidade de artigos excelentes disponíveis aqui no <a href="https://www.freecodecamp.org/news/search/?query=sql">freeCodeCamp</a>!)</p><h2 id="por-que-python-com-sql">Por que Python com SQL?</h2><p>Para analistas de dados e cientistas de dados, o Python apresenta muitas vantagens. Uma enorme variedade de bibliotecas de código aberto o torna uma ferramenta incrivelmente útil para qualquer analista de dados.</p><p>Nós temos o <a href="https://pandas.pydata.org/">pandas</a>, o <a href="https://numpy.org/">NumPy</a> e o <a href="https://vaex.readthedocs.io/en/latest/">Vaex</a> para análise de dados, o <a href="https://matplotlib.org/">Matplotlib</a>, o <a href="https://seaborn.pydata.org/">seaborn</a> e o <a href="https://bokeh.org/">Bokeh</a> para visualização, além do <a href="https://www.freecodecamp.org/news/p/5fe3a414-f0df-488b-9402-44d8edc12652/www.tensorflow.org">TensorFlow</a>, do <a href="https://scikit-learn.org/stable/">scikit-learn</a> e do <a href="https://pytorch.org/">PyTorch</a> para aprendizagem de máquina (além de muitas, muitas outras).</p><p>Com sua curva de aprendizagem (relativamente) fácil e versatilidade, não é de admirar que o Python seja <a href="https://stackoverflow.blog/2017/09/06/incredible-growth-python/">uma das linguagens de programação que mais crescem</a>.</p><p>Portanto, se optar por usar Python para análise de dados, vale a pena perguntar: de onde vêm todos esses dados?</p><p>Embora haja uma enorme variedade de fontes para conjuntos de dados, em muitos casos – particularmente, em empresas - os dados são armazenados em um banco de dados relacional. Os bancos de dados relacionais são uma maneira extremamente eficiente, poderosa e amplamente utilizada para <a href="https://pt.wikipedia.org/wiki/CRUD">criar, ler, atualizar e excluir</a> dados de todos os tipos.</p><p>Os sistemas de gerenciamento de bancos de dados relacionais (SGBDR) mais utilizados - <a href="https://www.oracle.com/database/">Oracle</a>, <a href="https://www.mysql.com/">MySQL</a>, <a href="https://en.wikipedia.org/wiki/Microsoft_SQL_Server">Microsoft SQL Server</a>, <a href="https://www.oracle.com/database/what-is-a-relational-database/">PostgreSQL</a>, <a href="https://en.wikipedia.org/wiki/IBM_DB2">IBM DB2</a> - usam a Linguagem de Consulta Estruturada (SQL, da sigla em inglês, <a href="https://en.wikipedia.org/wiki/SQL">Structured Query Language</a>) para acessar e modificar os dados.</p><p>Observe que cada SGBDR usa um tipo um pouco diferente de SQL. Portanto, o código SQL escrito para um geralmente não funcionará com outro sem modificações (normalmente pequenas). No entanto, os conceitos, estruturas e operações são, em grande parte, idênticos.</p><p>Isso quer dizer que, para um analista de dados, uma sólida compreensão de SQL é de grande importância. Saber como usar Python e SQL juntos dará a você uma vantagem ainda maior na hora de trabalhar com os seus dados.</p><p>O restante deste artigo será dedicado a mostrar exatamente como podemos fazer isso.</p><h2 id="para-come-ar">Para começar</h2><h3 id="requisitos-e-instala-o">Requisitos e instalação</h3><p>Para programar junto com este tutorial, você precisará do seu próprio <a href="https://www.python.org/downloads/">ambiente Python</a> configurado.</p><p>Eu uso a distribuição <a href="https://www.anaconda.com/">Anaconda</a>, mas há muitas maneiras de fazer isso. Basta pesquisar no Google "como instalar o Python" se precisar de ajuda. Você também pode usar o <a href="https://mybinder.org/">Binder</a> para programar usando um <a href="https://github.com/thecraigd/Python_SQL">Jupyter Notebook</a> associado.</p><p>Nós vamos usar o <a href="https://dev.mysql.com/downloads/mysql/">MySQL Community Server</a>, que é gratuito e amplamente utilizado na indústria. Se estiver utilizando o Windows, <a href="https://www.youtube.com/watch?v=2HQC94la6go" rel="noopener nofollow">este guia</a> (em inglês) o ajudará na hora de configurar. Aqui estão os guias para os usuários de <a href="https://www.youtube.com/watch?v=5BQ5GvjiAR4" rel="noopener nofollow">Mac</a> e <a href="https://www.youtube.com/watch?v=0o0tSaVQfV4" rel="noopener nofollow">Linux</a> &nbsp;(embora as instruções possam variar de acordo com a distribuição Linux utilizada).</p><p>Depois de configurados, precisaremos fazer com que eles se comuniquem.</p><p>Para isso, precisaremos instalar a biblioteca <a href="https://dev.mysql.com/doc/connector-python/en/">MySQL Connector</a> para o Python. Faça isso seguindo <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-installation.html">estas instruções</a>, ou simplesmente use o pip:</p><pre><code class="language-terminal">pip install mysql-connector-python</code></pre><p>Também utilizaremos a biblioteca <a href="https://pandas.pydata.org/pandas-docs/stable/getting_started/install.html">pandas</a>. Certifique-se de que ela também esteja instalada.</p><pre><code class="language-terminal">pip install pandas</code></pre><h3 id="importando-as-bibliotecas">Importando as bibliotecas</h3><p>Como em todo projeto em Python, a primeira coisa que devemos fazer é importar nossas bibliotecas.</p><p>É uma boa prática importar todas as bibliotecas que vamos usar no início do projeto. Assim, as pessoas que lerão ou revisarão nosso código saberão, até certo ponto, o que está por vir, sem surpresas.</p><p>Para este tutorial, utilizaremos apenas duas bibliotecas - o <a href="https://dev.mysql.com/doc/connector-python/en/">MySQL Connector</a> e o <a href="https://pandas.pydata.org/">pandas</a>.</p><pre><code class="language-python">import mysql.connector
from mysql.connector import Error
import pandas as pd</code></pre><p>Importamos a função Error separadamente para que tenhamos acesso fácil a ela em nossas funções.</p><h2 id="conectando-ao-mysql-server">Conectando ao MySQL Server</h2><p>A essa altura, já devemos ter o <a href="https://dev.mysql.com/downloads/mysql/">MySQL Community Server</a> configurado em nosso sistema. Agora, precisamos escrever um código em Python que nos permita estabelecer uma conexão com este servidor.</p><figure class="kg-card kg-code-card"><pre><code class="language-python">def create_server_connection(host_name, user_name, user_password):
    connection = None
    try:
        connection = mysql.connector.connect(
            host=host_name,
            user=user_name,
            passwd=user_password
        )
        print("MySQL Database connection successful")
    except Error as err:
        print(f"Error: '{err}'")

    return connection</code></pre><figcaption>Uma função para conectar ao nosso MySQL Server</figcaption></figure><p>É uma boa prática a criação de uma função para tornar reutilizável um código como esse, permitindo que ele seja utilizado repetidas vezes com o mínimo de esforço. Uma vez criado, você poderá reutilizá-lo em todos os seus projetos futuros e o seu “eu do futuro” será grato!</p><p>Vamos revisar o código, linha por linha, para entendermos o que está acontecendo aqui:</p><p>Na primeira linha, damos um nome à função (create_server_connection) e aos seus argumentos (host_name, user_name e user_password).</p><p>Na linha seguinte, encerramos quaisquer conexões existentes para que o servidor não fique confuso com várias conexões abertas.</p><p>Em seguida, usamos um &nbsp;<a href="https://www.w3schools.com/python/python_try_except.asp">bloco try-except</a> (texto em inglês) do Python para lidar com possíveis erros. A primeira parte tenta criar uma conexão com o servidor usando o <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-connect.html">método mysql.connector.connect()</a> (texto em inglês) e os detalhes especificados pelo usuário nos argumentos da função. Se isso funcionar, a função imprime uma pequena mensagem de sucesso.</p><p>O código referente ao bloco except imprime o erro que o MySQL Server retorna se, infelizmente, houver um erro.</p><p>Por fim, se a conexão for bem-sucedida, a função retornará um <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html">objeto de conexão</a> (texto em inglês).</p><p>Na prática, atribuímos o resultado dessa função a uma variável, que então se torna o nosso objeto de conexão. Podemos, depois disso, aplicar outros métodos, como o <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor.html">cursor</a> (texto em inglês), a ele e criar outros objetos úteis.</p><figure class="kg-card kg-code-card"><pre><code class="language-python">connection = create_server_connection("localhost", "root", pw)</code></pre><figcaption>Aqui, pw é uma variável, do tipo string, contendo a senha do usuário root para o nosso MySQL Server</figcaption></figure><p>O código abaixo deve resultar em uma mensagem de sucesso:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-146.png" class="kg-image" alt="image-146" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-146.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-146.png 790w" width="790" height="79" loading="lazy"><figcaption>U-húúú!</figcaption></figure><h3 id="criando-um-novo-banco-de-dados">Criando um novo banco de dados</h3><p>Agora que estabelecemos uma conexão, nosso próximo passo é criar um banco de dados em nosso servidor.</p><p>Neste tutorial, faremos isso uma única vez, mas, novamente, criaremos uma função reutilizável de modo que tenhamos um código que possamos reutilizar em projetos futuros.</p><pre><code class="language-python">def create_database(connection, query):
    cursor = connection.cursor()
    try:
        cursor.execute(query)
        print("Database created successfully")
    except Error as err:
        print(f"Error: '{err}'")</code></pre><p>Essa função recebe dois argumentos, connection (nosso objeto de conexão) e query (um código SQL que escreveremos na próxima etapa). Ela executa a consulta no servidor através da conexão.</p><p>Usamos o método <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor.html">cursor</a> do nosso objeto de conexão para criar um objeto do tipo cursor (o MySQL Connector usa o <a href="https://www.freecodecamp.org/portuguese/news/como-explicar-conceitos-de-programacao-orientada-a-objetos-para-uma-crianca-de-6-anos/">paradigma de programação orientado a objetos</a>, portanto, há muitos objetos herdando propriedades de objetos pai).</p><p>Este objeto cursor possui métodos como <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html">execute</a>, <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html">executemany</a> (que usaremos neste tutorial - textos em inglês) assim como vários outros métodos úteis.</p><p>Se ajudar, podemos pensar que o objeto cursor dá acesso ao cursor que fica piscando em um terminal do MySQL Server.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-148.png" class="kg-image" alt="image-148" width="104" height="32" loading="lazy"><figcaption>É disso que estamos falando.</figcaption></figure><p>Em seguida, definimos uma consulta para criar o banco de dados e executar a função:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-149-1.png" class="kg-image" alt="image-149-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-149-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-149-1.png 664w" width="664" height="100" loading="lazy"></figure><p>Todos os códigos SQL deste tutorial estão explicados <a href="https://towardsdatascience.com/tagged/sql-series">na minha série de tutoriais Introduction to SQL</a> (Introdução ao SQL, em inglês), e o código completo está disponível em um Jupyter Notebook neste <a href="https://github.com/thecraigd/Python_SQL">repositório do GitHub</a>. Portanto, não explicarei o que o código SQL faz neste tutorial.</p><p>No entanto, esse é talvez o código SQL mais simples possível. Se você pode ler em inglês, provavelmente pode descobrir o que ele faz!</p><p>Executar a função create_database com os argumentos acima resulta na criação de um banco de dados chamado 'school' em nosso servidor.</p><p>Por que nosso banco de dados é chamado de 'school' (escola)? Talvez agora seja um bom momento para examinarmos em mais detalhes o que vamos implementar exatamente neste tutorial.</p><h3 id="nosso-banco-de-dados">Nosso banco de dados</h3><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/ERD-1.png" class="kg-image" alt="ERD-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/ERD-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/ERD-1.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/02/ERD-1.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/ERD-1.png 1843w" sizes="(min-width: 1200px) 1200px" width="1843" height="1300" loading="lazy"><figcaption>Diagrama entidade-relacionamento do nosso banco de dados</figcaption></figure><p>Seguindo o exemplo da minha <a href="https://towardsdatascience.com/tagged/sql-series">série anterior</a>, implementaremos o banco de dados para a International Language School (Escola Internacional de Idiomas) - uma escola fictícia de treinamento de idiomas que oferece aulas de idiomas profissionais para clientes corporativos.</p><p>O <a href="https://www.lucidchart.com/pages/er-diagrams">Diagrama Entidade Relacionamento (DER)</a> (texto em inglês) apresenta as entidades (Teacher, Client, Course e Participant) e define as relações entre elas.</p><p>Todas as informações sobre o que é um DER e o que considerar ao criar um e projetar um banco de dados podem ser encontradas <a href="https://towardsdatascience.com/designing-a-relational-database-and-creating-an-entity-relationship-diagram-89c1c19320b2">neste artigo</a> (em inglês).</p><p>O código SQL, os requisitos do banco de dados e os dados para inclusão no banco de dados estão todos disponíveis <a href="https://github.com/thecraigd/SQL_School_Tutorial">neste repositório do GitHub</a>, mas você também verá tudo à medida que avançarmos neste tutorial.</p><h3 id="conectando-ao-banco-de-dados">Conectando ao banco de dados</h3><p>Agora que criamos um banco de dados no MySQL Server, podemos modificar nossa função create_server_connection para conectar diretamente a esse banco de dados.</p><p>Observe que é possível - comum, na verdade - ter vários bancos de dados em um servidor MySQL, então queremos nos conectar sempre e automaticamente ao banco de dados em que estamos interessados.</p><p>Podemos fazer da seguinte maneira:</p><pre><code class="language-python">def create_db_connection(host_name, user_name, user_password, db_name):
    connection = None
    try:
        connection = mysql.connector.connect(
            host=host_name,
            user=user_name,
            passwd=user_password,
            database=db_name
        )
        print("MySQL Database connection successful")
    except Error as err:
        print(f"Error: '{err}'")

    return connection</code></pre><p>Essa é exatamente a mesma função, mas agora temos mais um argumento - o nome do banco de dados - que é passado para o método connect().</p><h3 id="criando-uma-fun-o-para-execu-o-de-consultas">Criando uma função para execução de consultas</h3><p>A última função que criaremos (por enquanto) é extremamente vital - uma função de execução de consulta. Ela pegará nossas consultas SQL, armazenadas como strings do Python, e as passará para que o método cursor.execute() as execute no servidor.</p><pre><code class="language-python">def execute_query(connection, query):
    cursor = connection.cursor()
    try:
        cursor.execute(query)
        connection.commit()
        print("Query successful")
    except Error as err:
        print(f"Error: '{err}'")</code></pre><p>Essa função é idêntica à nossa função create_database, exceto por usar o método <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlconnection-commit.html">connection.commit()</a> para garantir que os comandos detalhados em nossas consultas SQL sejam implementados.</p><p>Essa função será nosso carro-chefe, que usaremos (junto com create_db_connection) para criar tabelas, estabelecer relacionamentos entre essas tabelas, preencher as tabelas com dados e atualizar e excluir registros em nosso banco de dados.</p><p>Se você for um especialista em SQL, essa função permitirá que você execute todos e quaisquer comandos e consultas complexas que você possa ter, diretamente de um script em Python. Ela pode ser uma ferramenta muito poderosa para gerenciar seus dados.</p><h2 id="criando-tabelas">Criando tabelas</h2><p>Agora estamos prontos para começar a executar comandos SQL em nosso servidor e começar a construir nosso banco de dados. A primeira coisa que queremos fazer é criar as tabelas necessárias.</p><p>Vamos começar com a tabela Teacher (professor, em inglês):</p><pre><code class="language-python">create_teacher_table = """
CREATE TABLE teacher (
  teacher_id INT PRIMARY KEY,
  first_name VARCHAR(40) NOT NULL,
  last_name VARCHAR(40) NOT NULL,
  language_1 VARCHAR(3) NOT NULL,
  language_2 VARCHAR(3),
  dob DATE,
  tax_id INT UNIQUE,
  phone_no VARCHAR(20)
  );
 """

connection = create_db_connection("localhost", "root", pw, db) # Connect to the Database
execute_query(connection, create_teacher_table) # Execute our defined query</code></pre><p>Primeiro, atribuímos nosso comando SQL (explicado em detalhes <a href="https://towardsdatascience.com/coding-and-implementing-a-relational-database-using-mysql-d9bc69be90f5">aqui</a>) a uma variável com um nome apropriado.</p><p>Neste caso, usamos a <a href="https://developers.google.com/edu/python/strings">notação de aspas triplas do Python para definir strings que se estendem por múltiplas linhas</a> (texto em inglês) para armazenar nossa consulta SQL. Então, nós a passamos para a função execute_query que a executará.</p><p>Observe que essa formatação de várias linhas é puramente para facilitar a leitura do código por humanos. Nem SQL nem Python 'se importam' se o comando SQL estiver distribuído dessa maneira. Desde que a sintaxe esteja correta, ambas as linguagens a aceitarão.</p><p>Para o bem dos humanos que lerão seu código (mesmo que seja apenas o você do futuro!), é muito útil empregar essa formatação para tornar o código mais legível e compreensível.</p><p>O mesmo vale para o uso de expressões do SQL em LETRAS MAIÚSCULAS. Esta é uma convenção amplamente usada e que é fortemente recomendada, mas o software real que executa o código não diferencia maiúsculas de minúsculas e tratará 'CREATE TABLE teacher' e 'create table teacher' como comandos idênticos.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-151.png" class="kg-image" alt="image-151" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-151.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-151.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-151.png 1084w" width="1084" height="118" loading="lazy"></figure><p>A execução deste código retorna nossas mensagens de sucesso. Também podemos verificar isso no client na linha de comando do MySQL Server:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-152.png" class="kg-image" alt="image-152" width="267" height="175" loading="lazy"></figure><p>Excelente! Agora vamos criar as tabelas restantes.</p><pre><code class="language-python">create_client_table = """
CREATE TABLE client (
  client_id INT PRIMARY KEY,
  client_name VARCHAR(40) NOT NULL,
  address VARCHAR(60) NOT NULL,
  industry VARCHAR(20)
);
 """

create_participant_table = """
CREATE TABLE participant (
  participant_id INT PRIMARY KEY,
  first_name VARCHAR(40) NOT NULL,
  last_name VARCHAR(40) NOT NULL,
  phone_no VARCHAR(20),
  client INT
);
"""

create_course_table = """
CREATE TABLE course (
  course_id INT PRIMARY KEY,
  course_name VARCHAR(40) NOT NULL,
  language VARCHAR(3) NOT NULL,
  level VARCHAR(2),
  course_length_weeks INT,
  start_date DATE,
  in_school BOOLEAN,
  teacher INT,
  client INT
);
"""


connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, create_client_table)
execute_query(connection, create_participant_table)
execute_query(connection, create_course_table)</code></pre><p>Esses comandos criarão as quatro tabelas necessárias para nossas quatro entidades.</p><p>Agora, vamos definir os relacionamentos entre elas e criar mais uma tabela para lidar com o relacionamento muitos-para-muitos entre as tabelas participant e course (participante e curso, em inglês, respectivamente). Veja mais detalhes <a href="https://towardsdatascience.com/designing-a-relational-database-and-creating-an-entity-relationship-diagram-89c1c19320b2">aqui</a> (texto em inglês).</p><p>Fazemos exatamente da mesma forma:</p><pre><code class="language-python">alter_participant = """
ALTER TABLE participant
ADD FOREIGN KEY(client)
REFERENCES client(client_id)
ON DELETE SET NULL;
"""

alter_course = """
ALTER TABLE course
ADD FOREIGN KEY(teacher)
REFERENCES teacher(teacher_id)
ON DELETE SET NULL;
"""

alter_course_again = """
ALTER TABLE course
ADD FOREIGN KEY(client)
REFERENCES client(client_id)
ON DELETE SET NULL;
"""

create_takescourse_table = """
CREATE TABLE takes_course (
  participant_id INT,
  course_id INT,
  PRIMARY KEY(participant_id, course_id),
  FOREIGN KEY(participant_id) REFERENCES participant(participant_id) ON DELETE CASCADE,
  FOREIGN KEY(course_id) REFERENCES course(course_id) ON DELETE CASCADE
);
"""

connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, alter_participant)
execute_query(connection, alter_course)
execute_query(connection, alter_course_again)
execute_query(connection, create_takescourse_table)</code></pre><p>Agora, nossas tabelas foram criadas, juntamente com as restrições apropriadas e as relações entre chaves primárias e chaves estrangeiras.</p><h3 id="preenchendo-as-tabelas">Preenchendo as tabelas</h3><p>A próxima etapa é adicionar alguns registros às tabelas. Novamente, usaremos a função execute_query para enviar nossos comandos SQL existentes ao servidor. Vamos começar mais uma vez com a tabela Teacher.</p><pre><code class="language-python">pop_teacher = """
INSERT INTO teacher VALUES
(1,  'James', 'Smith', 'ENG', NULL, '1985-04-20', 12345, '+491774553676'),
(2, 'Stefanie',  'Martin',  'FRA', NULL,  '1970-02-17', 23456, '+491234567890'), 
(3, 'Steve', 'Wang',  'MAN', 'ENG', '1990-11-12', 34567, '+447840921333'),
(4, 'Friederike',  'Müller-Rossi', 'DEU', 'ITA', '1987-07-07',  45678, '+492345678901'),
(5, 'Isobel', 'Ivanova', 'RUS', 'ENG', '1963-05-30',  56789, '+491772635467'),
(6, 'Niamh', 'Murphy', 'ENG', 'IRI', '1995-09-08',  67890, '+491231231232');
"""

connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, pop_teacher)</code></pre><p>Funcionou? Podemos verificar no cliente de linha de comando do MySQL:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-153.png" class="kg-image" alt="image-153" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-153.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-153.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-153.png 1189w" width="1189" height="300" loading="lazy"><figcaption>Parece bom!</figcaption></figure><p>Agora, vamos preencher as tabelas restantes.</p><pre><code class="language-python">pop_client = """
INSERT INTO client VALUES
(101, 'Big Business Federation', '123 Falschungstraße, 10999 Berlin', 'NGO'),
(102, 'eCommerce GmbH', '27 Ersatz Allee, 10317 Berlin', 'Retail'),
(103, 'AutoMaker AG',  '20 Künstlichstraße, 10023 Berlin', 'Auto'),
(104, 'Banko Bank',  '12 Betrugstraße, 12345 Berlin', 'Banking'),
(105, 'WeMoveIt GmbH', '138 Arglistweg, 10065 Berlin', 'Logistics');
"""

pop_participant = """
INSERT INTO participant VALUES
(101, 'Marina', 'Berg','491635558182', 101),
(102, 'Andrea', 'Duerr', '49159555740', 101),
(103, 'Philipp', 'Probst',  '49155555692', 102),
(104, 'René',  'Brandt',  '4916355546',  102),
(105, 'Susanne', 'Shuster', '49155555779', 102),
(106, 'Christian', 'Schreiner', '49162555375', 101),
(107, 'Harry', 'Kim', '49177555633', 101),
(108, 'Jan', 'Nowak', '49151555824', 101),
(109, 'Pablo', 'Garcia',  '49162555176', 101),
(110, 'Melanie', 'Dreschler', '49151555527', 103),
(111, 'Dieter', 'Durr',  '49178555311', 103),
(112, 'Max', 'Mustermann', '49152555195', 104),
(113, 'Maxine', 'Mustermann', '49177555355', 104),
(114, 'Heiko', 'Fleischer', '49155555581', 105);
"""

pop_course = """
INSERT INTO course VALUES
(12, 'English for Logistics', 'ENG', 'A1', 10, '2020-02-01', TRUE,  1, 105),
(13, 'Beginner English', 'ENG', 'A2', 40, '2019-11-12',  FALSE, 6, 101),
(14, 'Intermediate English', 'ENG', 'B2', 40, '2019-11-12', FALSE, 6, 101),
(15, 'Advanced English', 'ENG', 'C1', 40, '2019-11-12', FALSE, 6, 101),
(16, 'Mandarin für Autoindustrie', 'MAN', 'B1', 15, '2020-01-15', TRUE, 3, 103),
(17, 'Français intermédiaire', 'FRA', 'B1',  18, '2020-04-03', FALSE, 2, 101),
(18, 'Deutsch für Anfänger', 'DEU', 'A2', 8, '2020-02-14', TRUE, 4, 102),
(19, 'Intermediate English', 'ENG', 'B2', 10, '2020-03-29', FALSE, 1, 104),
(20, 'Fortgeschrittenes Russisch', 'RUS', 'C1',  4, '2020-04-08',  FALSE, 5, 103);
"""

pop_takescourse = """
INSERT INTO takes_course VALUES
(101, 15),
(101, 17),
(102, 17),
(103, 18),
(104, 18),
(105, 18),
(106, 13),
(107, 13),
(108, 13),
(109, 14),
(109, 15),
(110, 16),
(110, 20),
(111, 16),
(114, 12),
(112, 19),
(113, 19);
"""

connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, pop_client)
execute_query(connection, pop_participant)
execute_query(connection, pop_course)
execute_query(connection, pop_takescourse)</code></pre><p>Surpreendente! Acabamos de criar um banco de dados completo com relações, restrições e registros no MySQL, usando apenas comandos em Python.</p><p>Fizemos isso passo a passo para que o processo fosse compreensível. Mas a esta altura você já deve ter percebido que todos esses comandos podem facilmente ser incluídos em um script em Python e executados em um único comando no terminal.</p><h2 id="lendo-os-dados">Lendo os dados</h2><p>Agora, temos um banco de dados funcional com o qual podemos trabalhar. Como analista de dados, é provável que você entre em contato com bancos de dados existentes nas organizações em que trabalha. Será muito útil saber como extrair dados desses bancos de dados para que possam ser alimentados em seu pipeline de dados em Python. É nisso que vamos trabalhar a seguir.</p><p>Para isso, precisaremos de mais uma função, desta vez, usando <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-fetchall.html">cursor.fetchall()</a> em vez de <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlconnection-commit.html">cursor.commit()</a> (textos das duas funções em inglês). Com esta função, leremos dados do banco de dados sem fazer nenhuma alteração.</p><pre><code class="language-python">def read_query(connection, query):
    cursor = connection.cursor()
    result = None
    try:
        cursor.execute(query)
        result = cursor.fetchall()
        return result
    except Error as err:
        print(f"Error: '{err}'")</code></pre><p>Novamente, vamos implementar isso de uma maneira muito semelhante ao execute_query. Vamos testar com uma consulta simples para ver como funciona.</p><pre><code class="language-python">q1 = """
SELECT *
FROM teacher;
"""

connection = create_db_connection("localhost", "root", pw, db)
results = read_query(connection, q1)

for result in results:
  print(result)</code></pre><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-154.png" class="kg-image" alt="image-154" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-154.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-154.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-154.png 1171w" width="1171" height="454" loading="lazy"></figure><p>Exatamente o que estávamos esperando. A função também funciona com consultas mais complexas, como esta envolvendo um JOIN entre as tabelas de course e client (curso e cliente, em inglês, respectivamente).</p><pre><code class="language-python">q5 = """
SELECT course.course_id, course.course_name, course.language, client.client_name, client.address
FROM course
JOIN client
ON course.client = client.client_id
WHERE course.in_school = FALSE;
"""

connection = create_db_connection("localhost", "root", pw, db)
results = read_query(connection, q5)

for result in results:
  print(result)</code></pre><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-155.png" class="kg-image" alt="image-155" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-155.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-155.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-155.png 1188w" width="1188" height="240" loading="lazy"></figure><p>Muito bom.</p><p>Para nossos pipelines de dados e fluxos de trabalho em Python, podemos querer obter esses resultados em formatos diferentes para torná-los mais úteis ou prontos para manipulação.</p><p>Vamos ver alguns exemplos para entender como podemos fazer isso.</p><h3 id="formatando-os-resultados-em-uma-lista">Formatando os resultados em uma lista</h3><pre><code class="language-python">#Inicializa uma lista vazia 
from_db = []

# Percorrer os resultados e inseri-los à lista

# Retorna uma lista de tuplas
for result in results:
  result = result
  from_db.append(result)</code></pre><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-156.png" class="kg-image" alt="image-156" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-156.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-156.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-156.png 1387w" sizes="(min-width: 1200px) 1200px" width="1387" height="171" loading="lazy"></figure><h3 id="formatando-o-resultado-em-uma-lista-de-listas">Formatando o resultado em uma lista de listas</h3><pre><code class="language-python"># Retorna uma lista de listas
from_db = []

for result in results:
  result = list(result)
  from_db.append(result)</code></pre><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-157.png" class="kg-image" alt="image-157" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-157.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-157.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-157.png 1376w" sizes="(min-width: 1200px) 1200px" width="1376" height="169" loading="lazy"></figure><h3 id="formatando-o-resultado-em-um-dataframe-do-pandas">Formatando o resultado em um <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html">DataFrame do Pandas</a></h3><p>Para os analistas de dados usando Python, o <a href="https://pandas.pydata.org/pandas-docs/stable/index.html">pandas</a> (texto em inglês) é o nosso velho amigo, belo e confiável. É muito simples converter a saída do nosso banco de dados em um DataFrame. A partir daí, as possibilidades são infinitas!</p><pre><code class="language-python"># Retorna uma lista de listas e cria um DataFrame do Pandas
from_db = []

for result in results:
  result = list(result)
  from_db.append(result)


columns = ["course_id", "course_name", "language", "client_name", "address"]
df = pd.DataFrame(from_db, columns=columns)</code></pre><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-158.png" class="kg-image" alt="image-158" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-158.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-158.png 927w" width="927" height="316" loading="lazy"></figure><p>Espero que possa ver as possibilidades se desdobrando diante de você. Com apenas algumas linhas de código, podemos extrair facilmente todos os dados que podemos manipular dos bancos de dados relacionais em que eles residem e trazê-los para nossos pipelines de análise de dados de última geração. Isso é algo realmente útil.</p><h2 id="atualizando-registros">Atualizando registros</h2><p>Quando mantemos um banco de dados, às vezes precisaremos fazer alterações nos registros existentes. Nesta seção, veremos como fazer isso.</p><p>Digamos que a ILS seja notificada de que um de seus clientes existentes, a Big Business Federation, está mudando de escritório para 23 Fingiertweg, 14534 Berlin. Nesse caso, o administrador do banco de dados (nós!) precisará fazer algumas alterações.</p><p>Felizmente, podemos fazer isso com nossa função execute_query junto com a instrução <a href="https://dev.mysql.com/doc/refman/8.0/en/update.html">UPDATE</a> (texto em inglês) do SQL.</p><pre><code class="language-python">update = """
UPDATE client 
SET address = '23 Fingiertweg, 14534 Berlin' 
WHERE client_id = 101;
"""

connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, update)</code></pre><p>Note que a cláusula WHERE é muito importante. Se executarmos esse comando sem a cláusula WHERE, todos os endereços de todos os registros em nossa tabela Client serão atualizados para 23 Fingiertweg. Não é exatamente isso que queremos fazer.</p><p>Observe também que usamos "WHERE client_id = 101" na consulta UPDATE. Também seria possível usar "WHERE client_name = 'Big Business Federation'" ou "WHERE address = '123 Falschungstraße, 10999 Berlin'" ou mesmo "WHERE address LIKE '%Falschung%'".</p><p>O importante é que a cláusula WHERE nos permite identificar exclusivamente o registro (ou registros) que queremos atualizar.</p><h2 id="apagando-registros">Apagando registros</h2><p>Também é possível usar nossa função execute_query para excluir registros, usando <a href="https://dev.mysql.com/doc/refman/8.0/en/delete.html">DELETE</a> (texto em inglês).</p><p>Ao usar SQL com bancos de dados relacionais, precisamos ter cuidado ao usar o operador DELETE. Este não é o Windows. Não há um alerta dizendo "Tem certeza de que deseja excluir isso?" em uma janela de pop-up e não há uma lixeira para a reciclagem. Uma vez que excluímos algo, esse algo realmente se foi.</p><p>Dito isso, nós às vezes realmente precisamos apagar coisas. Então, vamos ver isso na prática, apagando um curso da nossa tabela Course.</p><p>Antes de mais nada, vamos nos lembrar dos cursos que temos.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-174.png" class="kg-image" alt="image-174" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-174.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-174.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-174.png 1082w" width="1082" height="558" loading="lazy"></figure><p>Digamos que o curso 20, 'Fortgeschrittenes Russisch' (que é 'Russo avançado' para você e para mim), está chegando ao fim. Então, precisamos removê-lo do nosso banco de dados.</p><p>A essa altura, você não ficará surpreso com a forma como fazemos isso - salve o comando SQL como uma string e, em seguida, passe-o para a nossa função execute_query.</p><pre><code class="language-python">delete_course = """
DELETE FROM course 
WHERE course_id = 20;
"""

connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, delete_course)</code></pre><p>Vamos verificar para confirmar que obtivemos o resultado pretendido:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-175.png" class="kg-image" alt="image-175" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-175.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-175.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-175.png 1068w" width="1068" height="538" loading="lazy"></figure><p>'Russo avançado' se foi, como esperávamos.</p><p>Esse comando também funciona para apagar colunas inteiras, usando <a href="https://www.w3schools.com/sql/sql_ref_drop_column.asp">DROP COLUMN</a> e tabelas inteiras, usando <a href="https://www.w3schools.com/sql/sql_ref_drop_table.asp">DROP TABLE</a> (ambos os textos de referência em inglês), mas não abordaremos esses comandos neste tutorial.</p><p>No entanto, vá em frente e experimente-os - não importa se você excluir uma coluna ou tabela de um banco de dados para uma escola fictícia. É uma boa ideia se familiarizar com esses comandos antes de passar para um ambiente de produção.</p><h3 id="e-o-crud">E o <a href="https://pt.wikipedia.org/wiki/CRUD">CRUD</a>?</h3><p>A essa altura, já podemos concluir as quatro operações principais para o armazenamento de dados persistentes.</p><p>Aprendemos a:</p><ul><li>Create (Criar) - bancos de dados, tabelas e registros inteiramente novos</li><li>Read (Ler) - extrair dados de um banco de dados e armazenar em diversos formatos</li><li>Update (Atualizar) - fazer alterações nos registros existentes no banco de dados</li><li>Delete (Apagar) - remover registros que não são mais necessários</li></ul><p>Poder fazer essas coisas é incrivelmente útil.</p><p>Antes de concluirmos, temos mais uma habilidade muito importante para aprender.</p><h2 id="criando-registros-a-partir-de-listas">Criando registros a partir de listas</h2><p>Vimos, ao preencher nossas tabelas, que podemos utilizar o comando SQL INSERT em nossa função execute_query para inserir registros em nosso banco de dados.</p><p>Dado que estamos usando Python para manipular nosso banco de dados SQL, seria útil poder obter uma estrutura de dados do Python, tal como uma <a href="https://www.w3schools.com/python/python_lists.asp">lista</a> (texto em inglês), e inseri-la diretamente em nosso banco de dados.</p><p>Isso pode ser útil quando queremos armazenar logs de atividade do usuário em um aplicativo de mídia social que escrevemos em Python ou entradas de usuários em uma página Wiki que criamos, por exemplo. Existem tantos usos possíveis para isso quantos você possa imaginar.</p><p>Esse método também é mais seguro se nosso banco de dados estiver aberto para nossos usuários a qualquer momento, pois ajuda a prevenir ataques de <a href="https://pt.wikipedia.org/wiki/Inje%C3%A7%C3%A3o_de_SQL">injeção de SQL</a>, que podem <a href="https://www.lucidchart.com/pages/er-diagrams">danificar ou até destruir</a> (texto em inglês) todo o nosso banco de dados.</p><p>Para fazer isso, escreveremos uma função usando o método <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html">executemany()</a>, em vez do método <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html">execute()</a> (textos de referência em inglês), mais simples, que usamos até agora.</p><pre><code class="language-python">def execute_list_query(connection, sql, val):
    cursor = connection.cursor()
    try:
        cursor.executemany(sql, val)
        connection.commit()
        print("Query successful")
    except Error as err:
        print(f"Error: '{err}'")</code></pre><p>Agora temos a função, precisamos definir um comando SQL ('sql') e uma lista contendo os valores que desejamos inserir no banco de dados ('val'). Os valores devem ser armazenados em uma <a href="https://www.w3schools.com/python/python_lists.asp">lista</a> de <a href="https://www.w3schools.com/python/python_tuples.asp">tuplas</a> (textos de referência em inglês), que é uma maneira bastante comum de armazenar dados em Python.</p><p>Para adicionar dois novos professores ao banco de dados, podemos escrever um código como este:</p><pre><code class="language-python">sql = '''
    INSERT INTO teacher (teacher_id, first_name, last_name, language_1, language_2, dob, tax_id, phone_no) 
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
    '''
    
val = [
    (7, 'Hank', 'Dodson', 'ENG', None, '1991-12-23', 11111, '+491772345678'), 
    (8, 'Sue', 'Perkins', 'MAN', 'ENG', '1976-02-02', 22222, '+491443456432')
]</code></pre><p>Observe aqui que no código 'sql' usamos o '%s' como um espaço reservado para nosso valor. A semelhança com o <a href="https://stackoverflow.com/questions/4288973/whats-the-difference-between-s-and-d-in-python-string-formatting/48660475">'%s'</a> para uma string em Python é apenas coincidência (e francamente, muito confusa), pois devemos usar '%s' para todos os tipos de dados (strings, inteiros, datas etc) com o MySQL Python Conector.</p><p>Você pode ver vários casos no <a href="https://stackoverflow.com/questions/20818155/not-all-parameters-were-used-in-the-sql-statement-python-mysql/20818201">Stackoverflow</a> em que alguém ficou confuso e tentou usar <a href="https://stackoverflow.com/questions/4288973/whats-the-difference-between-s-and-d-in-python-string-formatting/48660475">'%d'</a> para inteiros porque estava acostumado a fazer isso em Python. Isso não funcionará aqui - precisamos usar um '%s' para cada coluna para qual queremos adicionar um valor.</p><p>A função executemany, então, pega cada tupla em nossa lista 'val' e insere o valor relevante para aquela coluna no lugar do espaço reservado e executa o comando SQL para cada tupla contida na lista.</p><p>Isso pode ser feito para várias linhas de dados, desde que sejam formatadas corretamente. Em nosso exemplo, adicionaremos apenas dois novos professores, para fins ilustrativos, mas em princípio podemos adicionar quantos quisermos.</p><p>Vamos executar este comando e adicionar os professores ao nosso banco de dados.</p><pre><code class="language-python">connection = create_db_connection("localhost", "root", pw, db)
execute_list_query(connection, sql, val)</code></pre><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-177.png" class="kg-image" alt="image-177" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/image-177.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/image-177.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/image-177.png 1178w" width="1178" height="526" loading="lazy"></figure><p>Boas-vindas à ILS, Hank e Sue!</p><p>Esta é mais uma função muito útil, permitindo-nos pegar dados gerados em nossos scripts e aplicativos Python e inseri-los diretamente em nosso banco de dados.</p><h2 id="conclus-o">Conclusão</h2><p>Abordamos muitas coisas neste tutorial.</p><p>Aprendemos como usar o Python e o MySQL Connector para criar um banco de dados totalmente novo no MySQL Server, criar tabelas dentro desse banco de dados, definir as relações entre elas e preenchê-las com dados.</p><p>Abordamos como <a href="https://pt.wikipedia.org/wiki/CRUD">Criar, Ler, Atualizar e Apagar</a> dados em nosso banco de dados.</p><p>Vimos como extrair dados de bancos de dados existentes e carregá-los em pandas DataFrames, prontos para análise e trabalho adicional, aproveitando todas as possibilidades oferecidas pela stack <a href="https://www.pluralsight.com/guides/a-lap-around-the-pydata-stack">PyData</a> (texto em inglês).</p><p>Indo na outra direção, também aprendemos como pegar dados gerados por nossos scripts e aplicativos Python e gravá-los em um banco de dados onde eles podem ser armazenados com segurança para recuperação e manipulação posteriores.</p><p>Espero que este tutorial tenha ajudado você a ver como podemos usar Python e SQL juntos para poder manipular dados de forma ainda mais eficaz!</p><p>Se você quiser ver mais sobre os projetos e trabalhos do autor, visite o site do autor em <em><a href="https://www.craigdoesdata.de/">craigdoesdata.de</a>. </em>Se você tiver algum feedback sobre este tutorial, <em><a href="https://www.craigdoesdata.de/contact.html">entre em contato</a> com ele - </em>todos os comentários serão bem recebidos<em>!</em></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/logo.png" class="kg-image" alt="logo" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/logo.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/02/logo.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/02/logo.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/logo.png 2156w" sizes="(min-width: 720px) 720px" width="2156" height="400" loading="lazy"></figure> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
