Come misurare "ordinamento"


34

Mi chiedo se esiste un modo standard per misurare la "ordinamento" di un array? Un array che ha il numero medio di possibili inversioni sarebbe considerato al massimo indifferenziato? Con ciò voglio dire che è sostanzialmente il più lontano possibile dall'essere ordinati o in ordine inverso.

Risposte:


31

No, dipende dalla tua applicazione. Le misure di ordinamento sono spesso indicate come misure di disordine , che sono funzioni da a , dove è la raccolta di tutte le sequenze finite di interi non negativi distinti. Il sondaggio di Estivill-Castro e Wood [1] elenca e discute 11 diverse misure di disordine nel contesto di algoritmi di ordinamento adattivo.N<NRN<N

Il numero di inversioni potrebbe funzionare in alcuni casi, ma a volte è insufficiente. Un esempio dato in [1] è la sequenza

n/2+1,n/2+2,,n,1,,n/2

che ha un numero quadratico di inversioni, ma consiste solo di due corse ascendenti. È quasi ordinato, ma questo non viene catturato dalle inversioni.


[1] Estivill-Castro, Vladmir e Derick Wood. "Un sondaggio sugli algoritmi di ordinamento adattivo." ACM Computing Surveys (CSUR) 24.4 (1992): 441-476.


2
Il contesto sta cercando di capire perché quicksort si comporta in modo relativamente scarso su permutazioni casuali di n elementi in cui il numero di inversioni è vicino alla mediana.
Robert S. Barnes,

1
Ottimo esempio, sono esattamente le informazioni che stavo cercando.
Robert S. Barnes,

1
Estivill-Castro e legno è IL riferimento per questo di sicuro.
Pedro Dusso,

10

Mannila [1] assiomatizza la presortedness (con un focus sugli algoritmi basati sul confronto) come segue (parafrasando).

Lascia che un set totalmente ordinato. Quindi una mappatura da (le sequenze di elementi distinti da ) ai naturali è una misura di presortedness se soddisfa le condizioni di seguito.ΣmΣΣ

  1. Se è ordinato, allora .XΣm(X)=0

  2. Se con , e per tutti , quindi .X,YΣX=x1xnY=y1ynxi<xiyi<yji,j[1..n]m(X)=m(Y)

  3. Se è una sottosequenza di , allora .XYΣm(X)m(Y)

  4. Se per tutti e per alcuni , allora .xi<yji[1..|X|]j[1..|Y|]X,YΣm(XY)m(X)+m(Y)

  5. m(aX)|X|+m(X) per tutti e .XΣaEX

Esempi di tali misure sono il

  • numero di inversioni,
  • numero di swap,
  • il numero di elementi che non sono massimi da sinistra a destra e
  • la lunghezza di una sottosequenza crescente più lunga (sottratta dalla lunghezza di input).

Si noti che sono state definite distribuzioni casuali che utilizzano queste misure, ovvero tali da rendere più o meno probabili sequenze più / meno ordinate. Queste sono chiamate distribuzioni simili a Ewens [2, Ch. 4-5; 3, Esempio 12; 4], un caso speciale di cui è la cosiddetta distribuzione Mallows . I pesi sono parametrici in una costante e soddisfanoθ>0

Pr(X)=θm(X)YΣΣ|X|θm(Y) .

Nota come definisce la distribuzione uniforme (per tutti ).θ=1m

Poiché è possibile campionare le permutazioni con queste misure in modo efficiente, questo corpus di lavoro può essere utile nella pratica quando si confrontano gli algoritmi di ordinamento.


  1. Misure di presortedness e algoritmi di smistamento ottimali di H. Mannila (1985)
  2. Strutture combinatorie logaritmiche: un approccio probabilistico di R. Arratia, AD Barbour e S. Tavaré (2003)
  3. Sull'aggiunta di un elenco di numeri (e altri processi determinanti a dipendenza singola) di A. Borodin, P. Diaconis e J. Fulman (2010)
  4. Distribuzioni simili a Ewens e analisi degli algoritmi di N. Auger et al. (2016)

3

Ho la mia definizione di "ordinamento" di una sequenza.

Data qualsiasi sequenza [a, b, c, ...] la confrontiamo con la sequenza ordinata contenente gli stessi elementi, contiamo il numero di corrispondenze e lo dividiamo per il numero di elementi nella sequenza.

Ad esempio, data la sequenza [5,1,2,3,4]procediamo come segue:

1) ordina la sequenza: [1,2,3,4,5]

2) confrontare la sequenza ordinata con l'originale spostandola di una posizione alla volta e contando il numero massimo di corrispondenze:

        [5,1,2,3,4]
[1,2,3,4,5]                            one match

        [5,1,2,3,4]
  [1,2,3,4,5]                          no matches

        [5,1,2,3,4]
    [1,2,3,4,5]                        no matches

        [5,1,2,3,4]
      [1,2,3,4,5]                      no matches

        [5,1,2,3,4]
        [1,2,3,4,5]                    no matches

        [5,1,2,3,4]
          [1,2,3,4,5]                  4 matches

        [5,1,2,3,4]
            [1,2,3,4,5]                no matches

                ...

         [5,1,2,3,4]
                 [1,2,3,4,5]            no matches

3) Il numero massimo di partite è 4, possiamo calcolare la "ordinamento" come 4/5 = 0,8.

L'ordinamento di una sequenza ordinata sarebbe 1 e l'ordinamento di una sequenza con elementi disposti in ordine inverso sarebbe 1 / n.

L'idea alla base di questa definizione è stimare la quantità minima di lavoro che dovremmo fare per convertire qualsiasi sequenza nella sequenza ordinata. Nell'esempio sopra abbiamo bisogno di spostare solo un elemento, il 5 (ci sono molti modi, ma lo spostamento di 5 è il più efficiente). Quando gli elementi sarebbero posizionati in ordine inverso, dovremmo spostare 4 elementi. E quando la sequenza è stata ordinata, non è necessario alcun lavoro.

Spero che la mia definizione abbia un senso.


Bella idea Una definizione simile è Exc, la terza definizione di disturbo nel documento menzionato nella risposta di Juho . Exc è il numero di operazioni richieste per riordinare una sequenza in ordine ordinato.
Apass

Beh, forse, ho appena applicato la mia comprensione dell'entropia e del disordine alla sequenza di elementi :-)
Andrushenko Alexander

-2

Se hai bisogno di qualcosa di rapido e sporco (i segni di sommatoria mi spaventano) ho scritto una funzione di disordine super facile in C ++ per una classe chiamata Array che genera array int riempiti con numeri generati casualmente:

void Array::disorder() {
    double disorderValue = 0;
    int counter = this->arraySize;
    for (int n = 0; n < this->arraySize; n++) {
        disorderValue += abs(((n + 1) - array[n]));
//      cout << "disorderValue variable test value = " << disorderValue << endl;
        counter++;
    }
    cout << "Disorder Value = " << (disorderValue / this->arraySize) / (this->arraySize / 2) << "\n" << endl;
}

La funzione confronta semplicemente il valore di ciascun elemento con l'indice dell'elemento + 1 in modo che un array in ordine inverso abbia un valore di disordine di 1 e un array ordinato abbia un valore di disordine di 0. Non sofisticato, ma funzionante.

Michael


Questo non è un sito di programmazione. Sarebbe bastato definire la nozione di disturbo e menzionare che può essere calcolata in tempo lineare.
Yuval Filmus,
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.