Задача флага Нидерландов — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Новая страница: «'''Задача флага Нидерландов''' (англ. ''Dutch national flag problem, DNF''). Флаг Нидерландов состоит из тре...»)
 
Строка 1: Строка 1:
'''Задача флага Нидерландов''' (англ. ''Dutch national flag problem, DNF''). Флаг Нидерландов состоит из трех цветов: красного, белого и синего. Получая шары этих трех цветов, расположенных в случайном порядке, задача состоит в том, чтобы организовать их таким образом, что все шары одного цвета были вместе, а и их общие цвета шли в порядке как на данном флаге.
+
Флаг Нидерландов состоит из трех цветов: красного, белого и синего. Получая шары этих трех цветов, расположенных в случайном порядке, задача состоит в том, чтобы организовать их таким образом, что все шары одного цвета были вместе, а и их общие цвета шли в порядке как на данном флаге.
  
 
==Сортировка набора, состоящего из 0 и 1==
 
==Сортировка набора, состоящего из 0 и 1==
Строка 6: Строка 6:
 
Дан массив <tex>a[1..n]</tex> из <tex>n</tex> чисел <tex>0</tex> и <tex>1</tex>. Требуется разделить элементы друг от друга так, чтобы сначала оказались все <tex>0</tex>, а в конце <tex>1</tex>.
 
Дан массив <tex>a[1..n]</tex> из <tex>n</tex> чисел <tex>0</tex> и <tex>1</tex>. Требуется разделить элементы друг от друга так, чтобы сначала оказались все <tex>0</tex>, а в конце <tex>1</tex>.
 
}}
 
}}
 +
 
===Пример===
 
===Пример===
<tex> [0, 1, 0, 1, 0, 0, 1, 1, 1, 0] </tex><br>
+
<tex> [0, 1, 0, 1, 0, 0, 1, 1, 1, 0] => [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] </tex>
<tex> [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] </tex>
+
 
 
===Алгоритм===
 
===Алгоритм===
 
Будем поддерживать два указателя. Инициализируем первый индекс <tex>left = 1</tex> и второй индекс <tex>right = n</tex>.
 
Будем поддерживать два указателя. Инициализируем первый индекс <tex>left = 1</tex> и второй индекс <tex>right = n</tex>.
Строка 16: Строка 17:
 
# Уменьшаем <tex>right</tex> на <tex>1</tex> пока не <tex>a[right] = 1</tex>.
 
# Уменьшаем <tex>right</tex> на <tex>1</tex> пока не <tex>a[right] = 1</tex>.
 
# Если <tex>left < right</tex>, то меняем местами <tex>a[left]</tex> и <tex>a[right]</tex>, <tex>left\texttt{++}</tex>, <tex>right\texttt{--}</tex>.
 
# Если <tex>left < right</tex>, то меняем местами <tex>a[left]</tex> и <tex>a[right]</tex>, <tex>left\texttt{++}</tex>, <tex>right\texttt{--}</tex>.
 +
 
===Псевдокод===
 
===Псевдокод===
  sort('''int''' a[])
+
  '''int'''[] sort('''int'''[] a)
     '''int''' left = 1, right = n;
+
     '''int''' left = 0, right = n - 1;
 
     '''while''' (left < right)
 
     '''while''' (left < right)
 
         '''while''' (arr[left] == 0 '''and''' left < right)
 
         '''while''' (arr[left] == 0 '''and''' left < right)
Строка 35: Строка 37:
 
Дан массив <tex>a[1..n]</tex> из <tex>n</tex> чисел <tex>0</tex>, <tex>1</tex> и <tex>2</tex>. Требуется разделить их друг от друга так, чтобы сначала шли все <tex>0</tex>, потом все <tex>1</tex> и все <tex>2</tex> в конце.
 
Дан массив <tex>a[1..n]</tex> из <tex>n</tex> чисел <tex>0</tex>, <tex>1</tex> и <tex>2</tex>. Требуется разделить их друг от друга так, чтобы сначала шли все <tex>0</tex>, потом все <tex>1</tex> и все <tex>2</tex> в конце.
 
}}
 
}}
 +
 
===Пример===
 
===Пример===
<tex> [0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1] </tex><br>
+
<tex> [0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1] => [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2] </tex>
<tex> [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2] </tex>
+
 
 
===Алгоритм===
 
===Алгоритм===
 
Будем поддерживать три указателя. Инициализация: <tex>lo = 1; mid = 1; hi = n;</tex>.
 
Будем поддерживать три указателя. Инициализация: <tex>lo = 1; mid = 1; hi = n;</tex>.
Строка 51: Строка 54:
 
# <tex>a[mid..hi]</tex> неизвестны
 
# <tex>a[mid..hi]</tex> неизвестны
 
# <tex>a[hi+1..n] = 2</tex>
 
# <tex>a[hi+1..n] = 2</tex>
 +
 
===Псевдокод===
 
===Псевдокод===
  sort('''int''' a[])
+
  '''int'''[] sort('''int'''[] a)
     '''int''' lo = 1, mid = 1, hi = n;
+
     '''int''' lo = 0, mid = 0, hi = n - 1;
 
     '''while''' mid <tex>\leqslant</tex> right
 
     '''while''' mid <tex>\leqslant</tex> right
 
         '''switch''' (a[mid])
 
         '''switch''' (a[mid])
        '''case''' 0:
+
            '''case''' 0:
            swap(a[lo++], a[mid++])
+
                swap(a[lo++], a[mid++])
            break
+
                '''break'''
        '''case''' 1:
+
            '''case''' 1:
            mid++
+
                mid++
            break
+
                '''break'''
        '''case''' 2:
+
            '''case''' 2:
            swap(a[mid], a[hi--])
+
                swap(a[mid], a[hi--])
            break
+
                '''break'''
 
     '''return''' a
 
     '''return''' a
 
== См. также ==
 
== См. также ==

Версия 00:46, 8 июня 2015

Флаг Нидерландов состоит из трех цветов: красного, белого и синего. Получая шары этих трех цветов, расположенных в случайном порядке, задача состоит в том, чтобы организовать их таким образом, что все шары одного цвета были вместе, а и их общие цвета шли в порядке как на данном флаге.

Сортировка набора, состоящего из 0 и 1

Задача:
Дан массив [math]a[1..n][/math] из [math]n[/math] чисел [math]0[/math] и [math]1[/math]. Требуется разделить элементы друг от друга так, чтобы сначала оказались все [math]0[/math], а в конце [math]1[/math].


Пример

[math] [0, 1, 0, 1, 0, 0, 1, 1, 1, 0] =\gt [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] [/math]

Алгоритм

Будем поддерживать два указателя. Инициализируем первый индекс [math]left = 1[/math] и второй индекс [math]right = n[/math].

У будем делать следующее пока [math]left \lt right[/math]

  1. Увеличиваем [math]left[/math] на [math]1[/math] пока не [math]a[left] = 0[/math].
  2. Уменьшаем [math]right[/math] на [math]1[/math] пока не [math]a[right] = 1[/math].
  3. Если [math]left \lt right[/math], то меняем местами [math]a[left][/math] и [math]a[right][/math], [math]left\texttt{++}[/math], [math]right\texttt{--}[/math].

Псевдокод

int[] sort(int[] a)
    int left = 0, right = n - 1;
    while (left < right)
        while (arr[left] == 0 and left < right)
            left++
        while (arr[right] == 1 and left < right)
            right--
        if (left < right)
            swap(a[left], a[right])
            left++
            right--
    return a

Сортировка набора, состоящего из 0, 1 и 2

Задача:
Дан массив [math]a[1..n][/math] из [math]n[/math] чисел [math]0[/math], [math]1[/math] и [math]2[/math]. Требуется разделить их друг от друга так, чтобы сначала шли все [math]0[/math], потом все [math]1[/math] и все [math]2[/math] в конце.


Пример

[math] [0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1] =\gt [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2] [/math]

Алгоритм

Будем поддерживать три указателя. Инициализация: [math]lo = 1; mid = 1; hi = n;[/math].

У будем делать следующее пока [math]mid \leqslant right[/math]

  1. Если [math]a[mid] = 0[/math], то меняем местами [math]a[lo][/math] и [math]a[mid][/math], [math]lo\texttt{++}[/math], [math]mid\texttt{++}[/math].
  2. Если [math]a[mid] = 1[/math], то [math]mid\texttt{++}[/math].
  3. Если [math]a[mid] = 0[/math], то меняем местами [math]a[mid][/math] и [math]a[hi][/math], [math]hi\texttt{--}[/math].

Инвариант работы алгоритма:

  1. [math]a[1..lo-1] = 0[/math]
  2. [math]a[lo..mid-1] = 1[/math]
  3. [math]a[mid..hi][/math] неизвестны
  4. [math]a[hi+1..n] = 2[/math]

Псевдокод

int[] sort(int[] a)
    int lo = 0, mid = 0, hi = n - 1;
    while mid [math]\leqslant[/math] right
        switch (a[mid])
            case 0:
                swap(a[lo++], a[mid++])
                break
            case 1:
                mid++
                break
            case 2:
                swap(a[mid], a[hi--])
                break
    return a

См. также

Источники информации