Упорядоченное множество — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(maximum)
(Наивная реализация на массиве)
Строка 16: Строка 16:
 
Упорядоченное множество <tex>set</tex>, содержащее <tex>n</tex> элементов, можно реализовать с помощью массива <tex>elements[0..n-1]</tex>.
 
Упорядоченное множество <tex>set</tex>, содержащее <tex>n</tex> элементов, можно реализовать с помощью массива <tex>elements[0..n-1]</tex>.
  
Рассмотрим реализацию на примере отсортированного по неубыванию массива.
+
Рассмотрим реализацию на примере отсортированного по возрастанию целочисленного массива.
  
 
<code>
 
<code>
Строка 27: Строка 27:
 
<code>
 
<code>
 
  '''func''' insert(Set<T> s, T elem):
 
  '''func''' insert(Set<T> s, T elem):
    s.n = s.n + 1                                <font color=green>// Увеличиваем количество элементов множества на единицу,</font color=green>
+
     '''int''' i = 0
    Array.Resize(s.elements, s.n)                <font color=green>// увеличиваем размер массива с элементами множества на единицу.</font color=green>
+
    '''while''' i < s.n '''&&''' s.elements[i] < elem            <font color=green>// Ищем индекс первого элемента, большего elem.</font color=green>
     '''if''' elem % 2 == 0                             <font color=green>// Если элемент elem четный, то,</font color=green>
+
        i++
        '''int''' i = 0                                <font color=green>// ставим счетчик элементов массива на первый элемент,</font color=green>
+
    s.n = s.n + 1                                   <font color=green>// Увеличиваем количество элементов множества на единицу,</font color=green>
        '''while''' elem > s.elements[i]               <font color=green>// увеличиваем счетчик до тех пор, пока не найдем первый элемент, больший elem,</font color=green>
+
    Array.Resize(s.elements, s.n)                    <font color=green>// увеличиваем размер массива с элементами множества на единицу.</font color=green>
            i = i + 1
+
     '''if''' i != s.n - 1                                  <font color=green>// Если elem не максимальный,</font color=green>
        '''for''' j = s.n - 1 '''downto''' i+1               <font color=green>// сдвигаем все элементы, большие elem, на единицу вправо,</font color=green>
+
         '''int''' j
            s.elements[j] = s.elements[j - 1]
+
         '''for''' j = s.n - 2 '''downto''' i                     <font color=green>// то сдвигаем все элементы массива, большие elem,</font color=green>
        s.elements[i] = elem                      <font color=green>// вставляем элемент elem в ту ячейку массива, на которую указывает счетчик,</font color=green>
+
             s.elements[j + 1] = s.elements[j]       <font color=green>// на одну позицию вправо.</font color=green>
        s.even = s.even + 1                      <font color=green>// увеличиваем количество четных элементов на единицу.</font color=green>
+
    s.elements[i] = elem                            <font color=green>// Вставляем elem в нужное место.</font color=green>
     '''else'''                                          <font color=green>// Если элемент elem нечетный, то,</font color=green>
 
        '''int''' i = s.even                            <font color=green>// устанавливаем счетчик на первый нечетный элемент,</font color=green>
 
         '''while''' elem < s.elements[i]                <font color=green>// увеличиваем счетчик до тех пор, пока не найдем первый элемент, меньший elem,</font color=green>
 
            i = i + 1
 
         '''for''' j = s.n - 1 '''downto''' i+1                <font color=green>// сдвигаем все элементы, большие elem, на единицу вправо,</font color=green>
 
             s.elements[j] = s.elements[j - 1]
 
        s.elements[i] = elem                      <font color=green>// вставляем элемент elem в ту ячейку массива, на которую указывает счетчик,</font color=green>
 
        s.odd = s.odd + 1                        <font color=green>// увеличиваем количество нечетных элементов на единицу.</font color=green>
 
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.
Строка 52: Строка 44:
 
  '''func''' delete(Set<T> s, T elem):
 
  '''func''' delete(Set<T> s, T elem):
 
     '''int''' i = 0                                        <font color=green>// Устанавливаем счетчик на первый элемент.</font color=green>
 
     '''int''' i = 0                                        <font color=green>// Устанавливаем счетчик на первый элемент.</font color=green>
     '''while''' elem != s.elements[i] && i < s.n           <font color=green>// Ищем элемент elem.</font color=green>
+
     '''while''' i < s.n '''&&''' s.elements[i] != elem           <font color=green>// Ищем индекс элемента elem.</font color=green>
         i = i + 1
+
         i++
 
     '''if''' i != s.n                                      <font color=green>// Если элемент найден, то</font color=green>
 
     '''if''' i != s.n                                      <font color=green>// Если элемент найден, то</font color=green>
         '''for''' j = i '''to''' s.n - 2                          <font color=green>// сдвигаем все элементы массива, следующие за текущим, на единицу влево</font color=green>
+
         '''for''' j = i '''to''' s.n - 2                          <font color=green>// сдвигаем все элементы массива, большие elem,</font color=green>
             s.elements[j] = s.elements[j + 1]        <font color=green>// (тем самым удаляем элемент elem; последний элемент массива дублируется).</font color=green>
+
             s.elements[j] = s.elements[j + 1]        <font color=green>// на одну позицию влево (elem удаляется).</font color=green>
        '''if''' elem % 2 == 0                              <font color=green>// Если удаленный элемент был четным, то</font color=green>
+
         s.n = s.n - 1                                <font color=green>// Уменьшаем число элементов массива на единицу.</font color=green>
            s.even = s.even - 1                      <font color=green>// уменьшаем количество четных элементов на единицу,</font color=green>
 
        '''else'''                                          <font color=green>// в противном случае</font color=green>
 
            s.odd = s.odd - 1                        <font color=green>// уменьшаем количество нечетных элементов.</font color=green>
 
         s.n = s.n - 1                                <font color=green>// Уменьшаем общее число элементов на единицу.</font color=green>
 
 
         Array.Resize(s.elements, s.n)                <font color=green>// Удаляем дубликат последнего элемента.</font color=green>
 
         Array.Resize(s.elements, s.n)                <font color=green>// Удаляем дубликат последнего элемента.</font color=green>
 
</code>
 
</code>
Строка 67: Строка 55:
  
 
=== '''search''' ===
 
=== '''search''' ===
 +
Для нахождения результата используем бинарный поиск.
 +
 
<code>
 
<code>
 
  '''T''' search(Set<T> s, T elem):
 
  '''T''' search(Set<T> s, T elem):
    int i
+
     '''if''' s.elements[0] <= elem '''&&''' s.elements[s.n] >= elem        <font color=green>// Если элемент elem существует, то</font color=green>
     '''for''' i = 0 '''to''' s.n - 1
+
         '''int''' i = binSearch(s.elements, elem)                    <font color=green>// ищем индекс элемента elem</font color=green>
         '''if''' s.elements[i] == elem               <font color=green>// Если элемент elem существует,</font color=green>
+
        '''return''' s.elements[i]                                   <font color=green>// и выводим его значение.</font color=green>
            '''return''' s.elements[i]               <font color=green>// то выводим его,</font color=green>
+
     '''else'''                                                      <font color=green>// В противном случае</font color=green>
     '''return''' ''null''                               <font color=green>// в противном случае возвращаем ''null''.</font color=green>
+
        '''return''' ''null''                                           <font color=green>// возвращаем ''null''.</font color=green>
 
</code>
 
</code>
Время выполнения {{---}} <tex>O(n)</tex>.
+
Время выполнения {{---}} <tex>O(log n)</tex>.
  
  
Строка 101: Строка 91:
 
<code>
 
<code>
 
  '''T''' predecessor(Set<T> s, T elem):
 
  '''T''' predecessor(Set<T> s, T elem):
     '''int''' i
+
     '''if''' s.elements[0] < elem '''&&''' s.elements[s.n] >= elem        <font color=green>// Если элемент elem существует и не равен минимальному,</font color=green>
    '''for''' i = 1 '''to''' s.n - 1
+
         '''int''' i = binSearch(s.elements, elem)                    <font color=green>// то ищем индекс элемента elem</font color=green>
         '''if''' elem == s.elements[i]        <font color=green>// Если в массиве находим елемент elem,</font color=green>
+
        '''return''' s.elements[i - 1]                               <font color=green>// и выводим предшествующий ему элемент.</font color=green>
            '''return''' s.elements[i - 1]     <font color=green>// то выводим предшествующий ему элемент.</font color=green>
+
     '''else'''                                                      <font color=green>// В противном случае</font color=green>
     '''return''' ''null''                         <font color=green>// Иначе выводим ''null''.</font color=green>
+
        '''return''' ''null''                                           <font color=green>// возвращаем ''null''.</font color=green>
 
</code>
 
</code>
Время выполнения {{---}} <tex>O(n)</tex>.
+
Время выполнения {{---}} <tex>O(log n)</tex>.
  
  
Строка 113: Строка 103:
 
<code>
 
<code>
 
  '''T''' successor(Set<T> s, T elem):
 
  '''T''' successor(Set<T> s, T elem):
     '''int''' i
+
     '''if''' s.elements[0] <= elem '''&&''' s.elements[s.n] > elem        <font color=green>// Если элемент elem существует и не равен максимальному,</font color=green>
    '''for''' i = 1 '''to''' s.n - 1
+
         '''int''' i = binSearch(s.elements, elem)                    <font color=green>// то ищем индекс элемента elem</font color=green>
         '''if''' elem == s.elements[i]        <font color=green>// Если в массиве находим елемент elem,</font color=green>
+
        '''return''' s.elements[i + 1]                               <font color=green>// и выводим следующий за ним элемент.</font color=green>
            '''return''' s.elements[i + 1]     <font color=green>// то выводим следующий за ним элемент.</font color=green>
+
     '''else'''                                                      <font color=green>// В противном случае</font color=green>
     '''return''' ''null''                         <font color=green>// Иначе выводим ''null''.</font color=green>
+
        '''return''' ''null''                                           <font color=green>// возвращаем ''null''.</font color=green>
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.

Версия 21:14, 30 июня 2015

Упорядоченное множество (англ. ordered set) представляет собой коллекцию элементов, каждому из которых присваивается определенный ключ, отвечающий за порядок этого элемента в множестве. Бинарное отношение на упорядоченном множестве является отношением порядка.

Вполне упорядоченным множеством, которое явяется важнейшим частным случаем, называется упорядоченное множество, каждое непустое подмножество которого содержит минимальный элемент.

Операции над упорядоченным множеством

Над упорядоченным множеством [math]set[/math] заданы следующие операции:

  • [math]\mathrm {insert(set, elem)}[/math] — добавляет заданный элемент [math]elem[/math] в подходящее место множества [math]set[/math] (сохраняя свойство упорядоченности),
  • [math]\mathrm {delete(set, elem)}[/math] — удаляет элемент [math]elem[/math] (сохраняя свойство упорядоченности),
  • [math]\mathrm {search(set, elem)}[/math] — получает на вход искомое значение элемента [math]elem[/math] и возвращает найденный элемент множества [math]set[/math] или специальное значение [math]null[/math], если такого элемента нет,
  • [math]\mathrm {minimum(set)}[/math] — возвращает минимальный элемент множества [math]set[/math],
  • [math]\mathrm {maximum(set)}[/math] — возвращает максимальный элемент множества [math]set[/math],
  • [math]\mathrm {predecessor(set, elem)}[/math] — возвращает элемент, стоящий перед элементом [math]elem[/math] множества [math]set[/math].
  • [math]\mathrm {successor(set, elem)}[/math] — возвращает элемент, стоящий после элемента [math]elem[/math] множества [math]set[/math].

Наивная реализация на массиве

Упорядоченное множество [math]set[/math], содержащее [math]n[/math] элементов, можно реализовать с помощью массива [math]elements[0..n-1][/math].

Рассмотрим реализацию на примере отсортированного по возрастанию целочисленного массива.

struct Set<T>:
  int n                            // количество элементов множества
  T[n] elements                    // массив элементов множества типа T

insert

func insert(Set<T> s, T elem):
    int i = 0
    while i < s.n && s.elements[i] < elem            // Ищем индекс первого элемента, большего elem.
        i++
    s.n = s.n + 1                                    // Увеличиваем количество элементов множества на единицу,
    Array.Resize(s.elements, s.n)                    // увеличиваем размер массива с элементами множества на единицу.
    if i != s.n - 1                                  // Если elem не максимальный,
        int j
        for j = s.n - 2 downto i                     // то сдвигаем все элементы массива, большие elem,
            s.elements[j + 1] = s.elements[j]        // на одну позицию вправо.
    s.elements[i] = elem                             // Вставляем elem в нужное место.

Время выполнения — [math]O(n)[/math].

delete

func delete(Set<T> s, T elem):
    int i = 0                                         // Устанавливаем счетчик на первый элемент.
    while i < s.n && s.elements[i] != elem            // Ищем индекс элемента elem.
        i++
    if i != s.n                                       // Если элемент найден, то
        for j = i to s.n - 2                          // сдвигаем все элементы массива, большие elem,
            s.elements[j] = s.elements[j + 1]         // на одну позицию влево (elem удаляется).
        s.n = s.n - 1                                 // Уменьшаем число элементов массива на единицу.
        Array.Resize(s.elements, s.n)                 // Удаляем дубликат последнего элемента.

Время выполнения — [math]O(n)[/math].

search

Для нахождения результата используем бинарный поиск.

T search(Set<T> s, T elem):
    if s.elements[0] <= elem && s.elements[s.n] >= elem        // Если элемент elem существует, то
        int i = binSearch(s.elements, elem)                    // ищем индекс элемента elem
        return s.elements[i]                                   // и выводим его значение.
    else                                                       // В противном случае
        return null                                            // возвращаем null.

Время выполнения — [math]O(log n)[/math].


minimum

Первый элемент множества минимальный, так как массив отсортирован по неубыванию.

T minimum(Set<T> s):
    T min = s.elements[0]
    return min

Время выполнения — [math]O(1)[/math].

maximum

Выполняется аналогично операции [math]\mathrm {minimum(set)}[/math].

T maximum(Set<T> s):
    T max = s.elements[0]
    return max

Время выполнения — [math]O(1)[/math].

predecessor

T predecessor(Set<T> s, T elem):
    if s.elements[0] < elem && s.elements[s.n] >= elem         // Если элемент elem существует и не равен минимальному,
        int i = binSearch(s.elements, elem)                    // то ищем индекс элемента elem
        return s.elements[i - 1]                               // и выводим предшествующий ему элемент.
    else                                                       // В противном случае
        return null                                            // возвращаем null.

Время выполнения — [math]O(log n)[/math].


successor

T successor(Set<T> s, T elem):
    if s.elements[0] <= elem && s.elements[s.n] > elem         // Если элемент elem существует и не равен максимальному,
        int i = binSearch(s.elements, elem)                    // то ищем индекс элемента elem
        return s.elements[i + 1]                               // и выводим следующий за ним элемент.
    else                                                       // В противном случае
        return null                                            // возвращаем null.

Время выполнения — [math]O(n)[/math].


В случае, когда упорядоченность элементов коллекции не важна, возможно использование хешей.

Примеры

  • Пустое множество [math] \varnothing [/math],
  • множество натуральных чисел [math] \mathbb N [/math],
  • множество целых чисел [math] \mathbb Z [/math],
  • строки, отсортированные в лексикографическом порядке.

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

  • Кормен, Т., Лейзерсон, Ч., Ривест, Р., Алгоритмы: построение и анализ = Introduction to Algorithms / — 1-е изд. — Пер. с англ под ред. А. Шеня. — М.: МЦНМО, 2002.—960 с. — ISBN 5-900916-37-5
  • Александров П. С. Введение в теорию множеств и общую топологию. — М.: Наука, 1977. — 368 с.
  • Н. К. Верещагин, А. Шень. Часть 1. Начала теории множеств // Лекции по математической логике и теории алгоритмов. — 2-е изд., испр. — М.: МЦНМО, 2002. — 128 с.
  • Википедия — Упорядоченное множество