Domanda Perplessità codice C

ItsReal

Utente Electrum
30 Dicembre 2014
114
30
9
104
Salve a tutti, sto studiando gli array in C e sono arrivato ad un punto dove mi ritrovo ad ordinare in ordine crescente un array di interi.
La tecnica è quella del Bubble sorting e parte del codice è questo:
C:
#define SIZE 10

for(unsigned int pass = 1; pass < SIZE; pass++) {
     
      for(size_t i = 0; i < SIZE -1; i++) {
     
      if(a[i] > a[i + 1]) {
         int hold = a[i];
         a[i] = a[i +1];
         a[i + 1] = hold;
      }
   }

L'unica cosa che non riesco a capire è come lavorano assieme i due cicli For, non è possibile ottenere lo stesso risultato solo con il primo ciclo?

Ho provato a modificare il codice come segue ma ottengo un risultato non attendibile non riuscendo a capire come il compilatore interpreti il codice

Codice:
#define SIZE 10

for(unsigned int i = 1; i < SIZE; i++) {
     
     
     
      if(a[i] > a[i + 1]) {
         int hold = a[i];
         a[i] = a[i +1];
         a[i + 1] = hold;
     
   }
 
Il funzionamento del for è abbastanza semplice. Immagino che tu conosca già il meccanismo sintattico che ci sta dietro, quindi passo direttamente a farti un esempio. Il tuo codice è una cosa di questo tipo:
C:
for(int pass = 1; pass < SIZE; pass++) {
    for(int i = 0; i < SIZE - 1; i++) {
        printf("i = %d\n" i);
    }
}
quindi la variabile i assumerà i valori da 0 a SIZE-1 (senza stampare SIZE-1) per SIZE volte: in totale, avrai SIZE*(SIZE-1) print.

Immagino che il tuo dubbio principale sia sul funzionamento di bubblesort e sul perché sia necessario ripetere i SIZE-1 confronti fatti nel for interno debbano essere ripetuti per SIZE-2 volte (for esterno). Iniziamo a capire cosa fa il for interno e visto che si chiama bubblesort facciamo un analogia con le bolle in acqua. Partendo dal fondale e salendo verso la superficie, se la bolla in basso è più grande della bolla che gli sta immediatamente sopra effettui un sorpasso (ie., uno scambio di posizione). Così facendo è ovvio che la bolla più grande di tutte arriva in cima perché nel momento in cui la trovi quella sorpassa tutte le altre, ma cosa succede a tutte le altre? Nel momento in cui la bolla più grande di tutte sorpassa la seconda bolla più grande di tutte, questa seconda bolla non ha più modo di salire perché noi (la variabile i) stiamo seguendo la bolla che l'ha sorpassata. Per risolvere questo inconveniente, dobbiamo ripetere il for interno per (al più) SIZE-2 volte: la prima volta ci assicuriamo che la bolla più grande di tutte vada in cima, la seconda volta ci assicuriamo che la seconda bolla più grande di tutte vada dietro a quella più grande di tutte, e così via finché non mi assicuro che la seconda bolla più piccola abbia la possibilità di sorpassare la bolla più piccola. La bolla più piccola non dovrà fare alcun sorpasso, quindi non è necessario ripetere per SIZE-1 volte. Per farti capire meglio, aggiungo delle printf al tuo codice:
C:
#include <stdio.h>
#include <stdlib.h>

#define SIZE 10

void print_array(int *a, size_t n) {
  printf("[ ");
  for (size_t i = 0; i < n; i++) printf("%d ", a[i]);
  printf("]\n");
}

int main() {
  int a[SIZE] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
  print_array(a, SIZE);
  printf("\n");

  for (size_t pass = 1; pass < SIZE; pass++) {
    printf("pass number %zu\n", pass);
    for (size_t i = 0; i < SIZE - 1; i++) {
        printf("a[%zu] > a[%zu]  (%d > %d)  %c  ", i, i+1, a[i], a[i+1], a[i] > a[i+1] ? 'T' : 'F');
        if (a[i] > a[i + 1]) {
          int hold = a[i];
          a[i] = a[i + 1];
          a[i + 1] = hold;
        }
        print_array(a, SIZE);
    }
    printf("\n");
  }

  return 0;
}

Questo è l'output:
Codice:
[ 9 8 7 6 5 4 3 2 1 0 ]

pass number 1
a[0] > a[1]  (9 > 8)  T  [ 8 9 7 6 5 4 3 2 1 0 ]
a[1] > a[2]  (9 > 7)  T  [ 8 7 9 6 5 4 3 2 1 0 ]
a[2] > a[3]  (9 > 6)  T  [ 8 7 6 9 5 4 3 2 1 0 ]
a[3] > a[4]  (9 > 5)  T  [ 8 7 6 5 9 4 3 2 1 0 ]
a[4] > a[5]  (9 > 4)  T  [ 8 7 6 5 4 9 3 2 1 0 ]
a[5] > a[6]  (9 > 3)  T  [ 8 7 6 5 4 3 9 2 1 0 ]
a[6] > a[7]  (9 > 2)  T  [ 8 7 6 5 4 3 2 9 1 0 ]
a[7] > a[8]  (9 > 1)  T  [ 8 7 6 5 4 3 2 1 9 0 ]
a[8] > a[9]  (9 > 0)  T  [ 8 7 6 5 4 3 2 1 0 9 ]

pass number 2
a[0] > a[1]  (8 > 7)  T  [ 7 8 6 5 4 3 2 1 0 9 ]
a[1] > a[2]  (8 > 6)  T  [ 7 6 8 5 4 3 2 1 0 9 ]
a[2] > a[3]  (8 > 5)  T  [ 7 6 5 8 4 3 2 1 0 9 ]
a[3] > a[4]  (8 > 4)  T  [ 7 6 5 4 8 3 2 1 0 9 ]
a[4] > a[5]  (8 > 3)  T  [ 7 6 5 4 3 8 2 1 0 9 ]
a[5] > a[6]  (8 > 2)  T  [ 7 6 5 4 3 2 8 1 0 9 ]
a[6] > a[7]  (8 > 1)  T  [ 7 6 5 4 3 2 1 8 0 9 ]
a[7] > a[8]  (8 > 0)  T  [ 7 6 5 4 3 2 1 0 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 7 6 5 4 3 2 1 0 8 9 ]

pass number 3
a[0] > a[1]  (7 > 6)  T  [ 6 7 5 4 3 2 1 0 8 9 ]
a[1] > a[2]  (7 > 5)  T  [ 6 5 7 4 3 2 1 0 8 9 ]
a[2] > a[3]  (7 > 4)  T  [ 6 5 4 7 3 2 1 0 8 9 ]
a[3] > a[4]  (7 > 3)  T  [ 6 5 4 3 7 2 1 0 8 9 ]
a[4] > a[5]  (7 > 2)  T  [ 6 5 4 3 2 7 1 0 8 9 ]
a[5] > a[6]  (7 > 1)  T  [ 6 5 4 3 2 1 7 0 8 9 ]
a[6] > a[7]  (7 > 0)  T  [ 6 5 4 3 2 1 0 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 6 5 4 3 2 1 0 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 6 5 4 3 2 1 0 7 8 9 ]

pass number 4
a[0] > a[1]  (6 > 5)  T  [ 5 6 4 3 2 1 0 7 8 9 ]
a[1] > a[2]  (6 > 4)  T  [ 5 4 6 3 2 1 0 7 8 9 ]
a[2] > a[3]  (6 > 3)  T  [ 5 4 3 6 2 1 0 7 8 9 ]
a[3] > a[4]  (6 > 2)  T  [ 5 4 3 2 6 1 0 7 8 9 ]
a[4] > a[5]  (6 > 1)  T  [ 5 4 3 2 1 6 0 7 8 9 ]
a[5] > a[6]  (6 > 0)  T  [ 5 4 3 2 1 0 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 5 4 3 2 1 0 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 5 4 3 2 1 0 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 5 4 3 2 1 0 6 7 8 9 ]

pass number 5
a[0] > a[1]  (5 > 4)  T  [ 4 5 3 2 1 0 6 7 8 9 ]
a[1] > a[2]  (5 > 3)  T  [ 4 3 5 2 1 0 6 7 8 9 ]
a[2] > a[3]  (5 > 2)  T  [ 4 3 2 5 1 0 6 7 8 9 ]
a[3] > a[4]  (5 > 1)  T  [ 4 3 2 1 5 0 6 7 8 9 ]
a[4] > a[5]  (5 > 0)  T  [ 4 3 2 1 0 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 4 3 2 1 0 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 4 3 2 1 0 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 4 3 2 1 0 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 4 3 2 1 0 5 6 7 8 9 ]

pass number 6
a[0] > a[1]  (4 > 3)  T  [ 3 4 2 1 0 5 6 7 8 9 ]
a[1] > a[2]  (4 > 2)  T  [ 3 2 4 1 0 5 6 7 8 9 ]
a[2] > a[3]  (4 > 1)  T  [ 3 2 1 4 0 5 6 7 8 9 ]
a[3] > a[4]  (4 > 0)  T  [ 3 2 1 0 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 3 2 1 0 4 5 6 7 8 9 ]

pass number 7
a[0] > a[1]  (3 > 2)  T  [ 2 3 1 0 4 5 6 7 8 9 ]
a[1] > a[2]  (3 > 1)  T  [ 2 1 3 0 4 5 6 7 8 9 ]
a[2] > a[3]  (3 > 0)  T  [ 2 1 0 3 4 5 6 7 8 9 ]
a[3] > a[4]  (3 > 4)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 2 1 0 3 4 5 6 7 8 9 ]

pass number 8
a[0] > a[1]  (2 > 1)  T  [ 1 2 0 3 4 5 6 7 8 9 ]
a[1] > a[2]  (2 > 0)  T  [ 1 0 2 3 4 5 6 7 8 9 ]
a[2] > a[3]  (2 > 3)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[3] > a[4]  (3 > 4)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 1 0 2 3 4 5 6 7 8 9 ]

pass number 9
a[0] > a[1]  (1 > 0)  T  [ 0 1 2 3 4 5 6 7 8 9 ]
a[1] > a[2]  (1 > 2)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[2] > a[3]  (2 > 3)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[3] > a[4]  (3 > 4)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 0 1 2 3 4 5 6 7 8 9 ]

Fammi sapere se è tutto chiaro. Io ho intuiti che la tua domanda fosse più incentrata sul bubblesort, ma magari volevi una spiegazione generale sui cicli innestati.
 
  • Mi piace
Reazioni: JohnTop
Ultima modifica:
Salve a tutti, sto studiando gli array in C e sono arrivato ad un punto dove mi ritrovo ad ordinare in ordine crescente un array di interi.
La tecnica è quella del Bubble sorting e parte del codice è questo:
C:
#define SIZE 10

for(unsigned int pass = 1; pass < SIZE; pass++) {
 
      for(size_t i = 0; i < SIZE -1; i++) {
 
      if(a[i] > a[i + 1]) {
         int hold = a[i];
         a[i] = a[i +1];
         a[i + 1] = hold;
      }
   }

L'unica cosa che non riesco a capire è come lavorano assieme i due cicli For, non è possibile ottenere lo stesso risultato solo con il primo ciclo?

Ho provato a modificare il codice come segue ma ottengo un risultato non attendibile non riuscendo a capire come il compilatore interpreti il codice

Codice:
#define SIZE 10

for(unsigned int i = 1; i < SIZE; i++) {
 
 
 
      if(a[i] > a[i + 1]) {
         int hold = a[i];
         a[i] = a[i +1];
         a[i + 1] = hold;
 
   }
Ciao, molto semplicemente, per capire perché esistono quei due cicli for ti consiglio di fare una cosa: scrivi il tuo Array disordinato a mano (carta e penna), confronta ogni coppia di elementi nell'array, scambia la posizione del maggiore con quella del minore e avanza di un posto nel vettore. Ti accorgerai, scrivendolo a mano si ha più consapevolezza, che un solo ciclo for non permette di ordinare l'array del tutto. Continua a ripetere le operazioni di prima fino a quando il vettore non sarà ordinato completamente. Noterai che, se la dimensione dell'array è N, il numero di iterazioni totali sarà (N-1)^2. Difatti, formalmente, la complessità di questo algoritmo è definita di ordine O(n^2). Il ruolo del doppio for annidato (lo stesso meccanismo che si usa per iterare sulle componenti delle matrici) , dunque, è quello di iterare sull'array per (n-1)^2 volte. È anche un algoritmo pessimo, tra l'altro, perché ha una complessità quadratica. Infatti, sia nel caso peggiore (Array decrescente) sia nel caso migliore (Array già crescente) il numero di iterazioni resta invariato. Ah, dimenticavo, ovviamente le iterazioni dei due for annidati devono fermarsi sempre al valore (N - 1). Perché? Per il fatto che stiamo visitando gli elementi del vettore a due a due. Prova a immaginare se l'iterazione si fermasse all'ultimo elemento dell'array...ossia a N...cosa accadrebbe? Un errore di sconfinamento perché il codice, arrivato ad N, andrebbe a cercare un eventuale elemento N+1 nell'array (che non esiste) per fare lo scambio delle posizioni.
 
  • Mi piace
Reazioni: ItsReal
Il funzionamento del for è abbastanza semplice. Immagino che tu conosca già il meccanismo sintattico che ci sta dietro, quindi passo direttamente a farti un esempio. Il tuo codice è una cosa di questo tipo:
C:
for(int pass = 1; pass < SIZE; pass++) {
    for(int i = 0; i < SIZE - 1; i++) {
        printf("i = %d\n" i);
    }
}
quindi la variabile i assumerà i valori da 0 a SIZE-1 (senza stampare SIZE-1) per SIZE volte: in totale, avrai SIZE*(SIZE-1) print.

Immagino che il tuo dubbio principale sia sul funzionamento di bubblesort e sul perché sia necessario ripetere i SIZE-1 confronti fatti nel for interno debbano essere ripetuti per SIZE-2 volte (for esterno). Iniziamo a capire cosa fa il for interno e visto che si chiama bubblesort facciamo un analogia con le bolle in acqua. Partendo dal fondale e salendo verso la superficie, se la bolla in basso è più grande della bolla che gli sta immediatamente sopra effettui un sorpasso (ie., uno scambio di posizione). Così facendo è ovvio che la bolla più grande di tutte arriva in cima perché nel momento in cui la trovi quella sorpassa tutte le altre, ma cosa succede a tutte le altre? Nel momento in cui la bolla più grande di tutte sorpassa la seconda bolla più grande di tutte, questa seconda bolla non ha più modo di salire perché noi (la variabile i) stiamo seguendo la bolla che l'ha sorpassata. Per risolvere questo inconveniente, dobbiamo ripetere il for interno per (al più) SIZE-2 volte: la prima volta ci assicuriamo che la bolla più grande di tutte vada in cima, la seconda volta ci assicuriamo che la seconda bolla più grande di tutte vada dietro a quella più grande di tutte, e così via finché non mi assicuro che la seconda bolla più piccola abbia la possibilità di sorpassare la bolla più piccola. La bolla più piccola non dovrà fare alcun sorpasso, quindi non è necessario ripetere per SIZE-1 volte. Per farti capire meglio, aggiungo delle printf al tuo codice:
C:
#include <stdio.h>
#include <stdlib.h>

#define SIZE 10

void print_array(int *a, size_t n) {
  printf("[ ");
  for (size_t i = 0; i < n; i++) printf("%d ", a[i]);
  printf("]\n");
}

int main() {
  int a[SIZE] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
  print_array(a, SIZE);
  printf("\n");

  for (size_t pass = 1; pass < SIZE; pass++) {
    printf("pass number %zu\n", pass);
    for (size_t i = 0; i < SIZE - 1; i++) {
        printf("a[%zu] > a[%zu]  (%d > %d)  %c  ", i, i+1, a[i], a[i+1], a[i] > a[i+1] ? 'T' : 'F');
        if (a[i] > a[i + 1]) {
          int hold = a[i];
          a[i] = a[i + 1];
          a[i + 1] = hold;
        }
        print_array(a, SIZE);
    }
    printf("\n");
  }

  return 0;
}

Questo è l'output:
Codice:
[ 9 8 7 6 5 4 3 2 1 0 ]

pass number 1
a[0] > a[1]  (9 > 8)  T  [ 8 9 7 6 5 4 3 2 1 0 ]
a[1] > a[2]  (9 > 7)  T  [ 8 7 9 6 5 4 3 2 1 0 ]
a[2] > a[3]  (9 > 6)  T  [ 8 7 6 9 5 4 3 2 1 0 ]
a[3] > a[4]  (9 > 5)  T  [ 8 7 6 5 9 4 3 2 1 0 ]
a[4] > a[5]  (9 > 4)  T  [ 8 7 6 5 4 9 3 2 1 0 ]
a[5] > a[6]  (9 > 3)  T  [ 8 7 6 5 4 3 9 2 1 0 ]
a[6] > a[7]  (9 > 2)  T  [ 8 7 6 5 4 3 2 9 1 0 ]
a[7] > a[8]  (9 > 1)  T  [ 8 7 6 5 4 3 2 1 9 0 ]
a[8] > a[9]  (9 > 0)  T  [ 8 7 6 5 4 3 2 1 0 9 ]

pass number 2
a[0] > a[1]  (8 > 7)  T  [ 7 8 6 5 4 3 2 1 0 9 ]
a[1] > a[2]  (8 > 6)  T  [ 7 6 8 5 4 3 2 1 0 9 ]
a[2] > a[3]  (8 > 5)  T  [ 7 6 5 8 4 3 2 1 0 9 ]
a[3] > a[4]  (8 > 4)  T  [ 7 6 5 4 8 3 2 1 0 9 ]
a[4] > a[5]  (8 > 3)  T  [ 7 6 5 4 3 8 2 1 0 9 ]
a[5] > a[6]  (8 > 2)  T  [ 7 6 5 4 3 2 8 1 0 9 ]
a[6] > a[7]  (8 > 1)  T  [ 7 6 5 4 3 2 1 8 0 9 ]
a[7] > a[8]  (8 > 0)  T  [ 7 6 5 4 3 2 1 0 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 7 6 5 4 3 2 1 0 8 9 ]

pass number 3
a[0] > a[1]  (7 > 6)  T  [ 6 7 5 4 3 2 1 0 8 9 ]
a[1] > a[2]  (7 > 5)  T  [ 6 5 7 4 3 2 1 0 8 9 ]
a[2] > a[3]  (7 > 4)  T  [ 6 5 4 7 3 2 1 0 8 9 ]
a[3] > a[4]  (7 > 3)  T  [ 6 5 4 3 7 2 1 0 8 9 ]
a[4] > a[5]  (7 > 2)  T  [ 6 5 4 3 2 7 1 0 8 9 ]
a[5] > a[6]  (7 > 1)  T  [ 6 5 4 3 2 1 7 0 8 9 ]
a[6] > a[7]  (7 > 0)  T  [ 6 5 4 3 2 1 0 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 6 5 4 3 2 1 0 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 6 5 4 3 2 1 0 7 8 9 ]

pass number 4
a[0] > a[1]  (6 > 5)  T  [ 5 6 4 3 2 1 0 7 8 9 ]
a[1] > a[2]  (6 > 4)  T  [ 5 4 6 3 2 1 0 7 8 9 ]
a[2] > a[3]  (6 > 3)  T  [ 5 4 3 6 2 1 0 7 8 9 ]
a[3] > a[4]  (6 > 2)  T  [ 5 4 3 2 6 1 0 7 8 9 ]
a[4] > a[5]  (6 > 1)  T  [ 5 4 3 2 1 6 0 7 8 9 ]
a[5] > a[6]  (6 > 0)  T  [ 5 4 3 2 1 0 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 5 4 3 2 1 0 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 5 4 3 2 1 0 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 5 4 3 2 1 0 6 7 8 9 ]

pass number 5
a[0] > a[1]  (5 > 4)  T  [ 4 5 3 2 1 0 6 7 8 9 ]
a[1] > a[2]  (5 > 3)  T  [ 4 3 5 2 1 0 6 7 8 9 ]
a[2] > a[3]  (5 > 2)  T  [ 4 3 2 5 1 0 6 7 8 9 ]
a[3] > a[4]  (5 > 1)  T  [ 4 3 2 1 5 0 6 7 8 9 ]
a[4] > a[5]  (5 > 0)  T  [ 4 3 2 1 0 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 4 3 2 1 0 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 4 3 2 1 0 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 4 3 2 1 0 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 4 3 2 1 0 5 6 7 8 9 ]

pass number 6
a[0] > a[1]  (4 > 3)  T  [ 3 4 2 1 0 5 6 7 8 9 ]
a[1] > a[2]  (4 > 2)  T  [ 3 2 4 1 0 5 6 7 8 9 ]
a[2] > a[3]  (4 > 1)  T  [ 3 2 1 4 0 5 6 7 8 9 ]
a[3] > a[4]  (4 > 0)  T  [ 3 2 1 0 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 3 2 1 0 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 3 2 1 0 4 5 6 7 8 9 ]

pass number 7
a[0] > a[1]  (3 > 2)  T  [ 2 3 1 0 4 5 6 7 8 9 ]
a[1] > a[2]  (3 > 1)  T  [ 2 1 3 0 4 5 6 7 8 9 ]
a[2] > a[3]  (3 > 0)  T  [ 2 1 0 3 4 5 6 7 8 9 ]
a[3] > a[4]  (3 > 4)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 2 1 0 3 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 2 1 0 3 4 5 6 7 8 9 ]

pass number 8
a[0] > a[1]  (2 > 1)  T  [ 1 2 0 3 4 5 6 7 8 9 ]
a[1] > a[2]  (2 > 0)  T  [ 1 0 2 3 4 5 6 7 8 9 ]
a[2] > a[3]  (2 > 3)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[3] > a[4]  (3 > 4)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 1 0 2 3 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 1 0 2 3 4 5 6 7 8 9 ]

pass number 9
a[0] > a[1]  (1 > 0)  T  [ 0 1 2 3 4 5 6 7 8 9 ]
a[1] > a[2]  (1 > 2)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[2] > a[3]  (2 > 3)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[3] > a[4]  (3 > 4)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[4] > a[5]  (4 > 5)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[5] > a[6]  (5 > 6)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[6] > a[7]  (6 > 7)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[7] > a[8]  (7 > 8)  F  [ 0 1 2 3 4 5 6 7 8 9 ]
a[8] > a[9]  (8 > 9)  F  [ 0 1 2 3 4 5 6 7 8 9 ]

Fammi sapere se è tutto chiaro. Io ho intuiti che la tua domanda fosse più incentrata sul bubblesort, ma magari volevi una spiegazione generale sui cicli innestati.
Con l'esempio pratico ed il codice modificato ho capito molto meglio!

Grazie ;)