11c. Merge sort

2021-03-14
slides.com/jod/pt_11c

Docent: Jo Devriendt

Assistent: Ann Philips

Coördinator: Joost Vennekens

voornaam.achternaam@kuleuven.be

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Merge sort

Centraal idee

  • Samenvoegen (merge) van twee gesorteerde sequenties is eenvoudig
  • Array van lengte 1 is automatisch gesorteerd
    • Voeg samen tot array van 2, 4, 8, enz

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

[5][3][1][7][2][6][4][5]
[3 5][1 7][2 6][4 5]
[1 3 5 7][2 4 5 6]
[1 2 3 4 5 5 6 7]

Merge sort

[5 3 1 7 2 6 4 5]
[5 3 1 7] [2 6 4 5]
[5 3] [1 7] [2 6] [4 5]

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Merge sort gevisualiseerd

https://en.wikipedia.org/wiki/Merge_sort#/media/File:Merge_sort_animation2.gif

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Code

void voegSamen(int a[], int n1, int n2, int b[]);

void mergeSort(int a[], int n, int b[]);
  • a bevat de elementen om te sorteren
  • b is tijdelijke kopieer-array
  • voegSamen voegt de gesorteerde subarrays a[0..n1] en a[n1..n2] samen tot een gesorteerde array a[0..n2]
  • mergeSort splitst array in twee subarrays a[0..n/2] en a[n/2..n], sorteert ze recursief, en roept voegSamen op

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

void voegSamen(int a[],int n1,int n2,int b[]){
  for (int i = 0; i < n2; ++i) {
    b[i] = a[i];
  }
  int j = 0;
  int k = n1;
  for (int i = 0; i < n2; ++i) {
    if(j<n1 && (k==n2 || b[j]<=b[k])){
      a[i] = b[j];
      ++j;
    } else {
      a[i] = b[k];
      ++k;
    }
  }
}

Kopieer a naar b

Code

j en k zijn indexen in eerste en tweede subarray

Loop over alle indexen van a

Kopieer het kleinste nog niet gekopieerde element (b[j] of b[k]) naar a[i]

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

void mergeSort(int a[],int n,int b[]){
  if (n <= 1) {
    return;
  }
  int mid = n / 2;
  mergeSort(&a[0], mid, b);
  mergeSort(&a[mid], n - mid, b);
  voegSamen(a, mid, n, b);
}

Triviaal geval: array is gesorteerd

Code

recursieve operoep voor a[0..mid] en a[mid..n]

Voeg gesorteerde
a[0..mid] en a[mid..n] samen

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

#define N 8

int main() {
  int a[N] = {5,3,1,7,2,6,4,5};
  int b[N];
  mergeSort(a, N, b);
  for (int i = 0; i < N; ++i) {
    printf("%d ", a[i]);
  }
  printf("\n");
}

Code

$ ./a.out
1 2 3 4 5 5 6 7

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Analyse

  • n = #elementen
  • Iedere recursieve stap creëert twee +- half zo grote deelproblemen
    • de recursie gaat +-                stappen diep
  • Op elk recursieniveau doen we dan
    +- n stappen werk om, gesommeerd over alle subproblemen, de elementen samen te voegen
  • Total aantal operaties is altijd
O(\mathit{log}_2(n))
O(n)
[5][3][1][7][2][6][4][5]
[3 5][1 7][2 6][4 5]
[1 3 5 7][2 4 5 6]
[1 2 3 4 5 5 6 7]
[5 3 1 7 2 6 4 5]
[5 3 1 7] [2 6 4 5]
[5 3] [1 7] [2 6] [4 5]
\mathit{log}_2(n)
O(n\cdot \mathit{log}_2(n))

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Analyse

  • Merge sort gebruikt gegarandeerd hoogstens
    stappen
  • Sorteren vereist minstens                              stappen in het algemeen
    • Merge sort is optimaal!
  • Basisalgoritme van veel sorteerprocedures in programmeerbibliotheken
O(n\cdot \mathit{log}_2(n))
O(n\cdot \mathit{log}_2(n))

Programmeertechnieken [B-KUL-YI0855]

De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021

Samenvatting

  • Mergesort is een verdeel en heers-algoritme dat recursief sorteert
  • Heeft hoogstens                              stappen nodig
  • Is een optimaal sorteeralgoritme
O(n\cdot \mathit{log}_2(n))

11c. Merge sort

By Jo Devriendt

11c. Merge sort

  • 648