Ordinamento di inserzione e ordinamento di selezione


110

Sto cercando di capire le differenze tra l'ordinamento di inserzione e l'ordinamento di selezione.

Entrambi sembrano avere due componenti: un elenco non ordinato e un elenco ordinato. Entrambi sembrano prendere un elemento dall'elenco non ordinato e inserirlo nell'elenco ordinato nel posto giusto. Ho visto alcuni siti / libri che dicono che l'ordinamento di selezione lo fa scambiandolo uno alla volta mentre l'ordinamento per inserzione trova semplicemente il punto giusto e lo inserisce. Tuttavia, ho visto altri articoli dire qualcosa, dicendo che anche l'ordinamento per inserzione si scambia. Di conseguenza, sono confuso. C'è qualche fonte canonica?


8
Il wikipedia per l' ordinamento di selezione viene fornito con pseudo codice e graziose illustrazioni, così come quello per l'ordinamento per inserzione .
G. Bach

6
@ G.Bach - grazie per questo ... Ho letto entrambe le pagine più volte ma non capisco la differenza - da qui questa domanda.
eb80

3
Secondo Computerphile sono gli stessi: youtube.com/watch?v=pcJHkWwjNl4
Tristan Forward

Risposte:


186

Ordina selezione:

Dato un elenco, prendi l'elemento corrente e scambialo con l'elemento più piccolo sul lato destro dell'elemento corrente. Ordina selezione

Ordinamento di inserzione:

Dato un elenco, prendi l'elemento corrente e inseriscilo nella posizione appropriata dell'elenco, regolando l'elenco ogni volta che lo inserisci. È simile a disporre le carte in un gioco di carte. Ordinamento di inserzione

La complessità temporale dell'ordinamento di selezione è sempre n(n - 1)/2, mentre l'ordinamento per inserzione ha una complessità temporale migliore rispetto alla sua complessità nel caso peggiore n(n - 1)/2. In genere ci vorranno confronti minori o uguali allora n(n - 1)/2.

Fonte: http://cheetahonfire.blogspot.com/2009/05/selection-sort-vs-insertion-sort.html


2
@Nikolay - Questo è appena copiato da cheetahonfire.blogspot.com/2009/05/… che ho già letto. C'è qualcosa di più concreto dato che ho letto articoli contrastanti.
eb80

5
La differenza principale è il passaggio di selezione. L'ordinamento di selezione seleziona quello più piccolo e lo scambia con il primo L'ordinamento di inserimento inserisce quello corrente nella sua posizione appropriata
Nikolay Kostov

6
@ eb80 Non sono sicuro di quale materiale stai leggendo, ma non vedo come un esempio possa essere più concreto di questo?
G. Bach

23
Ma per quanto riguarda il numero di swap? La selezione fa sempre n (n-1) / 2 confronti, ma nel peggiore dei casi farà sempre e solo n-1 scambi. Nel caso peggiore, Insertion farà n (n-1) / 2 confronti così come n (n-1) / 2 swap.
Jason Goemaat

2
@Adorn Nessuno di questi sono algoritmi divide et impera.
Asky McAskface

63

Sia l'ordinamento per inserzione che l'ordinamento per selezione hanno un ciclo esterno (su ogni indice) e un ciclo interno (su un sottoinsieme di indici). Ogni passaggio del ciclo interno espande la regione ordinata di un elemento, a scapito della regione non ordinata, finché non esaurisce gli elementi non ordinati.

La differenza sta in ciò che fa il ciclo interno:

  • Nell'ordinamento della selezione, il ciclo interno si trova sugli elementi non ordinati . Ogni passaggio seleziona un elemento e lo sposta nella posizione finale (all'estremità corrente della regione ordinata).

  • Nell'ordinamento per inserimento, ogni passaggio del ciclo interno itera sugli elementi ordinati . Gli elementi ordinati vengono spostati finché il ciclo non trova la posizione corretta in cui inserire il successivo elemento non ordinato.

Quindi, in un ordinamento di selezione, gli elementi ordinati vengono trovati nell'ordine di output e rimangono inseriti una volta trovati. Al contrario, in un ordinamento per inserzione, gli elementi non ordinati rimangono inseriti fino a quando non vengono consumati nell'ordine di input, mentre gli elementi della regione ordinata continuano a spostarsi.

Per quanto riguarda lo scambio: l'ordinamento di selezione esegue uno scambio per passaggio del ciclo interno. L'ordinamento per inserzione in genere salva l'elemento da inserire come temp prima del ciclo interno, lasciando spazio al ciclo interno per spostare gli elementi ordinati verso l'alto di uno, quindi copia tempnel punto di inserimento in seguito.


23

SELEZIONE ORDINA
Supponiamo che ci sia un array di numeri scritti in un modo particolare / casuale e diciamo di dover disporre in ordine crescente .. quindi, prendi un numero alla volta e sostituiscili con il n. disponibile nell'elenco. facendo questo passaggio, alla fine otterremo il risultato desiderato.

inserisci qui la descrizione dell'immagine



ORDINA PER INSERIMENTO
Tenendo presente il presupposto simile ma l'unica differenza è che questa volta stiamo selezionando un numero alla volta e inserendolo nella parte presordinata, che ha ridotto i confronti e quindi è più efficiente.

inserisci qui la descrizione dell'immagine


Dai un'occhiata a mycodeschool su Youtube. Tuttavia, questa risposta complimenta quanto spiegato nei video di 2 algoritmi su youtube.
JaydeepW

21

È possibile che la confusione sia dovuta al fatto che stai confrontando una descrizione dell'ordinamento di un elenco collegato con una descrizione dell'ordinamento di un array . Ma non posso esserne sicuro, dal momento che non hai citato le tue fonti.

Il modo più semplice per comprendere gli algoritmi di ordinamento è spesso quello di ottenere una descrizione dettagliata dell'algoritmo (cose non vaghe come "questo tipo usa lo scambio. Da qualche parte. Non sto dicendo dove"), procurati alcune carte da gioco (5-10 dovrebbero essere sufficienti per algoritmi di ordinamento semplici) ed eseguire l'algoritmo manualmente.

Ordinamento selezione: esplora i dati non ordinati cercando l'elemento più piccolo rimanente, quindi scambialo nella posizione immediatamente successiva ai dati ordinati. Ripeti fino al termine. Se si ordina un elenco, non è necessario scambiare l'elemento più piccolo in posizione, è possibile invece rimuovere il nodo dell'elenco dalla sua vecchia posizione e inserirlo nella nuova.

Ordinamento per inserzione: prendi l'elemento immediatamente dopo i dati ordinati, scansiona i dati ordinati per trovare il posto dove metterlo e mettilo lì. Ripeti fino al termine.

L'ordinamento per inserzione può utilizzare lo scambio durante la sua fase di "scansione", ma non è necessario e non è il modo più efficiente a meno che non si stia ordinando un array di un tipo di dati che: (a) non può essere spostato, ma solo copiato o scambiato; e (b) è più costoso da copiare che da scambiare. Se l'ordinamento per inserzione utilizza lo scambio, il modo in cui funziona è che si cerca simultaneamente il luogo e ci si inserisce il nuovo elemento, scambiando ripetutamente il nuovo elemento con l'elemento immediatamente precedente, fintanto che l'elemento precedente è più grande di esso. Una volta raggiunto un elemento che non è più grande, hai trovato la posizione corretta e passi al nuovo elemento successivo.


1
Questo è molto utile ... L'ultimo paragrafo arriva alla confusione che stavo avendo, che derivava dalle varianti di ogni tipo.
eb80

1
+1 per aver notato che l'uso
dell'ordinamento

11

La logica per entrambi gli algoritmi è abbastanza simile. Entrambi hanno un sotto-array parzialmente ordinato all'inizio dell'array. L'unica differenza è il modo in cui cercano l'elemento successivo da inserire nella matrice ordinata.

  • Ordinamento di inserimento : inserisce l'elemento successivo nella posizione corretta;

  • Selezione selezione : seleziona l'elemento più piccolo e lo scambia con l'elemento corrente;

Inoltre, l' ordinamento di inserimento è stabile, al contrario dell'ordinamento di selezione .

Ho implementato entrambi in Python, e vale la pena notare quanto siano simili:

def insertion(data):
    data_size = len(data)
    current = 1
    while current < data_size:
        for i in range(current):
            if data[current] < data[i]:
                temp = data[i]
                data[i] = data[current]
                data[current] = temp

        current += 1

    return data

Con una piccola modifica è possibile realizzare l'algoritmo di ordinamento della selezione.

def selection(data):
    data_size = len(data)
    current = 0
    while current < data_size:
        for i in range(current, data_size):
            if data[i] < data[current]:
                temp = data[i]
                data[i] = data[current]
                data[current] = temp

        current += 1

    return data

scusa, mi chiedevo perché (algoritmo di ordinamento della selezione), i dati [i] vengono scambiati con i dati [correnti] ogni volta che i dati [i] sono più piccoli. Nell'ordinamento di selezione di base / originale (?), Troviamo il valore minimo tra range (i, data_size) e scambiamo i dati [i] con quel valore minimo ... è un po 'diverso ...
Tony Ma

4

In poche parole, penso che l'ordinamento di selezione cerchi prima il valore più piccolo nell'array, quindi esegua lo scambio mentre l'ordinamento per inserzione prende un valore e lo confronta con ogni valore lasciato (dietro di esso). Se il valore è inferiore, si scambia. Quindi, lo stesso valore viene nuovamente confrontato e se è più piccolo di quello dietro, scambia di nuovo. Spero che abbia un senso!


4

In breve,

Ordinamento selezione: seleziona il primo elemento dall'array non ordinato e confrontalo con gli elementi non ordinati rimanenti. È simile al Bubble sort, ma invece di scambiare ogni elemento più piccolo, mantiene aggiornato l'indice dell'elemento più piccolo e lo scambia alla fine di ogni ciclo .

Ordinamento di inserzione: è opposto all'ordinamento di selezione in cui seleziona il primo elemento dal sotto-array non ordinato e lo confronta con il sotto-array ordinato e inserisce l'elemento più piccolo dove si trova e sposta tutti gli elementi ordinati dalla sua destra al primo elemento non ordinato.


3

Farò ancora un altro tentativo: considera cosa succede nel caso fortunato di un array quasi ordinato.

Durante l'ordinamento, si può pensare che l'array abbia due parti: lato sinistro - ordinato, lato destro - non ordinato.

Ordinamento per inserzione: seleziona il primo elemento non ordinato e prova a trovarne una posizione nella parte già ordinata. Dato che cerchi da destra a sinistra, potrebbe benissimo accadere che il primo elemento ordinato a cui stai confrontando (il più grande, più a destra nella parte sinistra) sia più piccolo dell'elemento selezionato, quindi puoi immediatamente continuare con l'elemento successivo non ordinato.

Selezione selezione: scegli il primo elemento non ordinato e prova a trovare l'elemento più piccolo dell'intera parte non ordinata e scambia questi due se lo desideri. Il problema è che, poiché la parte giusta non è ordinata, devi pensare ogni volta a ogni elemento, poiché non puoi essere sicuro se ci sia o meno un elemento ancora più piccolo di quello scelto.

A proposito, questo è esattamente ciò che heapsort migliora con l'ordinamento della selezione: è in grado di trovare l'elemento più piccolo molto più rapidamente a causa dell'heap .


3

Selezione dell'ordinamento: quando inizi a costruire la sottoelenco ordinata, l'algoritmo garantisce che la sottoelenco ordinata sia sempre completamente ordinata, non solo in termini di elementi propri ma anche in termini di matrice completa, cioè sia sottoelenco ordinata che non ordinata. Quindi il nuovo elemento più piccolo una volta trovato dalla sottolista non ordinata verrebbe semplicemente aggiunto alla fine della sottolista ordinata.

Ordinamento di inserzione: l'algoritmo divide nuovamente l'array in due parti, ma qui l'elemento viene prelevato dalla seconda parte e inserito nella posizione corretta nella prima parte. Questo non garantisce mai che la prima parte sia ordinata in termini di matrice completa, sebbene ovviamente nel passaggio finale ogni elemento si trovi nella sua posizione ordinata corretta.


3

Entrambi gli algoritmi generalmente funzionano in questo modo

Passaggio 1: prendi quindi il prossimo elemento non ordinato dall'elenco non ordinato

Passaggio 2: inseriscilo nel posto giusto nell'elenco ordinato.

Uno dei passaggi è più semplice per un algoritmo e viceversa.

Ordinamento di inserzione : prendiamo il primo elemento dell'elenco non ordinato, lo mettiamo nell'elenco ordinato, da qualche parte . Sappiamo dove prendere l'elemento successivo (la prima posizione nell'elenco non ordinato), ma richiede un po 'di lavoro per trovare dove metterlo ( da qualche parte ). Il passaggio 1 è facile.

Ordinamento di selezione : prendiamo l'elemento da qualche parte dall'elenco non ordinato, quindi lo mettiamo nell'ultima posizione dell'elenco ordinato. Dobbiamo trovare l'elemento successivo (molto probabilmente non si trova nella prima posizione dell'elenco non ordinato , ma piuttosto, da qualche parte ) quindi inserirlo alla fine dell'elenco ordinato. Il passaggio 2 è facile


2

Il ciclo interno dell'ordinamento per inserimento passa attraverso gli elementi già ordinati (contrariamente all'ordinamento per selezione). Ciò gli consente di interrompere il ciclo interno quando viene trovata la posizione corretta . Che significa che:

  1. Il ciclo interno attraverserà solo la metà dei suoi elementi in un caso medio.
  2. Il ciclo interno verrà interrotto anche prima se l'array è quasi ordinato.
  3. Il ciclo interno si interromperà immediatamente se l'array è già ordinato, rendendo lineare la complessità dell'ordinamento per inserzione in questo caso.

L'ordinamento della selezione dovrà sempre passare attraverso tutti gli elementi del ciclo interno. Ecco perché l'ordinamento per inserzione è principalmente preferito all'ordinamento per selezione. Ma, d'altra parte, l'ordinamento di selezione esegue molti meno scambi di elementi, il che potrebbe essere più importante in alcuni casi.


1

Fondamentalmente l'ordinamento per inserimento funziona confrontando due elementi alla volta e l'ordinamento per selezione seleziona l'elemento minimo dall'intero array e lo ordina.

Concettualmente l'ordinamento per inserzione continua a ordinare la sottoelenco confrontando due elementi fino a quando l'intero array viene ordinato mentre l'ordinamento per selezione seleziona l'elemento minimo e lo scambia alla prima posizione, il secondo elemento minimo alla seconda posizione e così via.

L'ordinamento di inserimento può essere visualizzato come:

    for(i=1;i<n;i++)
        for(j=i;j>0;j--)
            if(arr[j]<arr[j-1])
                temp=arr[j];
                arr[j]=arr[j-1];
                arr[j-1]=temp;

L'ordinamento della selezione può essere visualizzato come:

    for(i=0;i<n;i++)
        min=i;
        for(j=i+1;j<n;j++)
        if(arr[j]<arr[min])
        min=j;
        temp=arr[i];
        arr[i]=arr[min];
        arr[min]=temp;

1

La scelta di questi 2 algoritmi di ordinamento dipende dalla struttura dati utilizzata.

Quando usi gli array, usa l'ordinamento di selezione (anche se perché, quando puoi usare qsort?). Quando utilizzi elenchi collegati, utilizza l'ordinamento per inserimento.

Questo è perché:

  • L'attraversamento di elenchi collegati è più costoso degli array.
  • L'inserimento di elenchi collegati è molto più economico degli array.

L'ordinamento per inserzione inserisce il nuovo valore al centro del segmento ordinato. Quindi, i dati devono essere "respinti". Tuttavia, quando si utilizza un elenco collegato, ruotando 2 puntatori, si è effettivamente spinto indietro l'intero elenco. In un array, è necessario eseguire scambi n - i per ripristinare i valori, il che può essere molto costoso.

L'ordinamento della selezione viene sempre aggiunto alla fine, quindi non presenta questo problema quando si utilizzano gli array. Quindi, i dati non devono essere "respinti".


0

Una semplice spiegazione potrebbe essere la seguente:

Dato : un array o un elenco di numeri non ordinato.

Dichiarazione del problema : per ordinare l'elenco / matrice di numeri in ordine crescente per comprendere la differenza tra l'ordinamento di selezione e l'ordinamento di inserimento.

Ordinamento di inserzione:Puoi vedere l'elenco dall'alto verso il basso per una più facile comprensione. Consideriamo il primo elemento come il nostro valore minimo iniziale. Ora, l'idea è che attraversiamo ogni indice di quella lista / matrice in modo lineare per scoprire se c'è qualche altro elemento in qualsiasi indice che ha un valore inferiore al valore minimo iniziale. Se troviamo un tale valore, scambiamo semplicemente i valori nei loro indici, cioè supponiamo che 15 fosse il valore iniziale minimo all'indice 1 e durante l'attraversamento lineare degli indici, ci imbattiamo in un numero con valore minore, diciamo 7 all'indice 9 Ora, questo valore 7 all'indice 9 viene scambiato con l'indice 1 avente 15 come valore. Questo attraversamento continuerà a fare il confronto con il valore dell'indice corrente con gli indici rimanenti da scambiare con il valore più piccolo. Questo continua fino al penultimo indice della lista / matrice,

Ordina selezione:Supponiamo che il primo elemento indice della lista / matrice sia ordinato. Ora dall'elemento al secondo indice, lo confrontiamo con il suo indice precedente per vedere se il valore è inferiore. L'attraversamento potrebbe essere visualizzato in due parti, ordinate e non ordinate. Si potrebbe visualizzare un controllo di confronto tra non ordinato e ordinato per un dato indice nell'elenco / matrice. Supponiamo che tu abbia valore 19 all'indice 1 e valore 10 all'indice 3. Consideriamo l'attraversamento dal non ordinato all'ordinato, cioè da destra a sinistra. Quindi, diciamo che dobbiamo ordinare all'indice 3. Vediamo che ha un valore inferiore all'indice 1 quando confrontiamo da destra a sinistra. Una volta identificato, mettiamo semplicemente questo numero 10 dell'indice 3 al posto dell'indice 1 avente valore 19. Il valore originale 19 dell'indice 1 viene spostato di una posizione a destra.

Non ho aggiunto alcun codice poiché sembra che la domanda riguardi la comprensione del concetto di metodo di attraversamento.


0

L'ordinamento di inserzione non scambia le cose. Anche se fa uso di una variabile temp, il punto di utilizzare temp var è quando abbiamo trovato un valore in un indice inferiore rispetto al valore del suo indice precedente, spostiamo il valore maggiore al posto del valore minore indice che sovrascriverebbe le cose. Quindi usiamo la temp var da sostituire all'indice precedente. Esempio: 10, 20, 30, 50, 40. iterazione 1: 10, 20, 30, 50, 50. [temp = 40] iterazione 2: 10,20, 30, 40 (valore della temperatura), 50. Quindi, basta inserire un valore nella posizione desiderata da una variabile.

Ma quando consideriamo l'ordinamento della selezione, troviamo prima l'indice con un valore inferiore e scambiamo quel valore con il valore del primo indice e continuiamo a scambiare ripetutamente fino a quando tutti gli indici non vengono ordinati. Questo è esattamente lo stesso dello scambio tradizionale di due numeri. Esempio: 30, 20, 10, 40, 50. Iterazione 1: 10, 20, 30, 40, 50. Qui temp var è usato esclusivamente per lo scambio.


0

L'ordinamento per inserzione fa molto di più scambiando quella selezione. Ecco un esempio:

inserisci qui la descrizione dell'immagine


0

Quello che hanno in comune è che entrambi usano una partizione per distinguere tra la parte ordinata dell'array e quella non ordinata.

La differenza è che con l'ordinamento di selezione si ha la garanzia che la parte ordinata dell'array non cambierà quando si aggiungono elementi alla partizione ordinata.

Il motivo è che la selezione cerca il minimo dell'insieme non ordinato e lo aggiunge subito dopo l'ultimo elemento dell'insieme ordinato, aumentando così l'insieme ordinato di 1.

L'inserimento, d'altra parte, si preoccupa solo dell'elemento successivo che viene incontrato, che è il primo elemento nella parte non ordinata dell'array. Prenderà questo elemento e lo inserirà semplicemente al suo posto nel set ordinato.

L'ordinamento per inserzione sarà in genere sempre un candidato migliore per gli array che sono ordinati solo parzialmente perché stai sprecando operazioni per trovare il minimo.

Conclusione:

L'ordinamento della selezione aggiunge in modo incrementale un elemento alla fine trovando l'elemento minimo nella sezione non ordinata.

L'ordinamento per inserzione propaga il primo elemento trovato nella sezione non ordinata in qualsiasi punto della sezione ordinata.


0

Sebbene la complessità temporale dell'ordinamento della selezione e dell'ordinamento per inserzione sia la stessa, è n (n - 1) / 2. L'ordinamento dell'inserimento delle prestazioni medie è migliore. Testato sulla mia cpu i5 con 30000 numeri interi casuali, l'ordinamento di selezione ha richiesto in media 1,5 secondi, mentre l'ordinamento per inserzione richiede in media 0,6 secondi.


Benvenuto in StackOverflow e grazie per la risposta. Molto probabilmente puoi vedere che molte persone hanno già contribuito con belle risposte con illustrazioni visive. Ad esempio Nikolay Kostov 7 anni fa ha affermato che la complessità temporale è la stessa solo nel caso peggiore per l'ordinamento per inserzione. Se pensi che abbia torto, ti invitiamo ad espandere la tua risposta con maggiori dettagli.
Maxim Sagaydachny il

-1

In parole povere, (e probabilmente il modo più semplice per raggiungere una comprensione di alto livello del problema)

Bubble sort è simile a stare in fila e cercare di ordinare da soli in base all'altezza. Continui a cambiare con la persona accanto a te finché non sei nel posto giusto. Questo avviene da sinistra (o da destra a seconda dell'implementazione) e continui a cambiare finché tutti non sono ordinati.

Nell'ordinamento di selezione, tuttavia, ciò che stai facendo è simile a disporre una mano di carte. Guardi le carte, prendi la più piccola, la metti completamente a sinistra e così via.


3
Chiede però la differenza tra selezione e ordinamento di inserzione
XuDing

-1

selezione -selezionare un elemento particolare (il più basso) e scambiarlo con l'elemento i (no di iterazione) esimo. (cioè, primo, secondo, terzo .......) quindi, creando l'elenco ordinato su un lato.

inserimento- confronto primo con secondo confronta terzo con secondo e primo confronta quarto con terzo, secondo e primo ...

un collegamento in cui vengono confrontati tutti gli ordinamenti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.