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

Материал из Викиконспекты
Перейти к: навигация, поиск
(Примеры)
Строка 5: Строка 5:
 
== Операции над упорядоченным множеством ==
 
== Операции над упорядоченным множеством ==
 
Над упорядоченным множеством <tex>Set</tex> заданы следующие операции:
 
Над упорядоченным множеством <tex>Set</tex> заданы следующие операции:
* <tex>\mathrm {insert(Set, elem, key)}</tex> {{---}} добавляет заданный элемент <tex>elem</tex>, имеющий ключ <tex>key</tex>, в подходящее место множества <tex>Set</tex> (сохраняя свойство упорядоченности),
+
* <tex>\mathrm {insert(set, elem)}</tex> {{---}} добавляет заданный элемент <tex>elem</tex> в подходящее место множества <tex>set</tex> (сохраняя свойство упорядоченности),
* <tex>\mathrm {delete(Set, key)}</tex> {{---}} удаляет элемент, имеющий ключ <tex>key</tex> (сохраняя свойство упорядоченности),
+
* <tex>\mathrm {delete(set, elem)}</tex> {{---}} удаляет элемент <tex>elem</tex> (сохраняя свойство упорядоченности),
* <tex>\mathrm {search(Set, key)}</tex> {{---}} получает на вход искомый ключ <tex>key</tex> и возвращает указатель на элемент множества <tex>Set</tex> или специальное значение <tex>null</tex>, если такого элемента нет,
+
* <tex>\mathrm {search(set, elem)}</tex> {{---}} получает на вход искомое значение элемента <tex>elem</tex> и возвращает найденный элемент множества <tex>set</tex> или специальное значение <tex>null</tex>, если такого элемента нет,
* <tex>\mathrm {minimum(Set)}</tex> {{---}} возвращает указатель на минимальный элемент множества <tex>Set</tex>,
+
* <tex>\mathrm {minimum(set)}</tex> {{---}} возвращает минимальный элемент множества <tex>set</tex>,
* <tex>\mathrm {maximum(Set)}</tex> {{---}} возвращает указатель на максимальный элемент множества <tex>Set</tex>,
+
* <tex>\mathrm {maximum(set)}</tex> {{---}} возвращает максимальный элемент множества <tex>set</tex>,
* <tex>\mathrm {predecessor(Set, elem)}</tex> {{---}} возвращает указатель на элемент, стоящий перед элементом <tex>elem</tex> множества <tex>Set</tex>.
+
* <tex>\mathrm {predecessor(set, elem)}</tex> {{---}} возвращает элемент, стоящий перед элементом <tex>elem</tex> множества <tex>set</tex>.
* <tex>\mathrm {successor(Set, elem)}</tex> {{---}} возвращает указатель на элемент, стоящий после элемента <tex>elem</tex> множества <tex>Set</tex>.
+
* <tex>\mathrm {successor(set, elem)}</tex> {{---}} возвращает элемент, стоящий после элемента <tex>elem</tex> множества <tex>set</tex>.
  
 
== Наивная реализация на массиве ==
 
== Наивная реализация на массиве ==
Упорядоченное множество <tex>Set</tex>, содержащее <tex>n</tex> элементов, можно реализовать с помощью массива <tex>elements[0..n-1]</tex>. Оно будет обладать следующими полями:
+
Упорядоченное множество <tex>set</tex>, содержащее <tex>n</tex> элементов, можно реализовать с помощью массива <tex>elements[0..n-1]</tex>. Рассмотрим реализацию на примере следующего множества: {0, 2, 4, ..., 5, 3, 1}.
* <tex>elem</tex> {{---}} элемент множества,
 
* <tex>key</tex> {{---}} ключ элемента.
 
  
 
<code>
 
<code>
  '''struct''' Set<T>
+
  '''struct''' set<T>:
   '''int''' n                           <font color=green>// количество элементов множества</font color=green>
+
  '''int''' even                        <font color=green>// количество четных элементов множества</font color=green>
   '''T'''[] elements                     <font color=green>// массив элементов множества типа T</font color=green>
+
  '''int''' odd                          <font color=green>// количество нечетных элементов множества</font color=green>
 +
   '''int''' n = even + odd              <font color=green>// общее количество элементов множества</font color=green>
 +
   '''T'''[n] elements                   <font color=green>// массив элементов множества типа T</font color=green>
 
</code>
 
</code>
  
 
=== '''insert''' ===
 
=== '''insert''' ===
 
<code>
 
<code>
  '''func''' insert(Set, elem, key):
+
  '''func''' insert(set<T> s, T elem):
     Set.n = Set.n + 1                     <font color=green>//Увеличиваем размер массива на единицу</font color=green>
+
     s.n = s.n + 1                                 <font color=green>// Увеличиваем количество элементов множества на единицу,</font color=green>
     Set.elements[key] = elem              <font color=green>//и добавляем элемент с ключом key.</font color=green>
+
    Array.Resize(s.elements, s.n)                <font color=green>// увеличиваем размер массива с элементами множества на единицу.</font color=green>
 +
    '''if''' elem % 2 == 0                              <font color=green>// Если элемент elem четный, то,</font color=green>
 +
        '''int''' i = 0                                <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.even = s.even + 1                      <font color=green>// увеличиваем количество четных элементов на единицу.</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(1)</tex>.
 
Время выполнения {{---}} <tex>O(1)</tex>.
Строка 34: Строка 50:
 
=== '''delete''' ===
 
=== '''delete''' ===
 
<code>
 
<code>
  '''func''' delete(Set, key):
+
  '''func''' delete(set<T> s, T elem):
     '''if''' key < Set.n - 1                               <font color=green>//Если key {{---}} не последний элемент,</font color=green>
+
     '''int''' i = 0                                        <font color=green>// Устанавливаем счетчик на первый элемент.</font color=green>
         '''for''' i = key '''to''' Set.n - 2                     <font color=green>//то сдвигаем все элементы множества, начиная с key, влево.</font color=green>
+
    '''while''' elem != s.elements[i] && i < s.n           <font color=green>// Ищем элемент elem.</font color=green>
             Set.elements[i] = Set.elements[i + 1]
+
        i = i + 1
         Set.n = Set.n - 1                            <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>
 +
             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.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>
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.
Строка 45: Строка 69:
 
=== '''search''' ===
 
=== '''search''' ===
 
<code>
 
<code>
  '''T''' search(Set, key):
+
  '''T''' search(set<T> s, T elem):
     '''for''' i = 0 '''to''' Set.n - 1
+
    int i
         '''if''' i == key                                <font color=green>//Если элемент с ключом key существует, возвращаем указатель на него,</font color=green>
+
     '''for''' i = 0 '''to''' s.n - 1
             '''return''' *(Set.elements + key)
+
         '''if''' s.elements[i] == elem              <font color=green>// Если элемент elem существует,</font color=green>
     '''return''' ''null''                                   <font color=green>//в противном случае возвращаем ''null''.</font color=green>
+
             '''return''' s.elements[i]              <font color=green>// то выводим его,</font color=green>
 +
     '''return''' ''null''                               <font color=green>// в противном случае возвращаем ''null''.</font color=green>
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.
Строка 56: Строка 81:
 
=== '''minimum''' ===
 
=== '''minimum''' ===
 
<code>
 
<code>
  '''T''' minimum(Set):
+
  '''T''' minimum(set<T> s):
     '''T''' min = Set.elements[0]              <font color=green>//Принимаем первый элемент множества за минимальный.</font color=green>
+
     '''T''' min = s.elements[0]              <font color=green>// Принимаем первый элемент множества за минимальный.</font color=green>
     '''int''' res = 0
+
     '''int''' i
     '''for''' i = 1 '''to''' Set.n - 1
+
     '''for''' i = 1 '''to''' s.n - 1
         '''if''' min > Set.elements[i]          <font color=green>//Если есть элементы меньше min,</font color=green>
+
         '''if''' min > s.elements[i]          <font color=green>// Ищем минимальный элемент множества</font color=green>
             min = Set.elements[i]         <font color=green>//то записывает элемент в min</font color=green>
+
             min = s.elements[i]
            res = i                      <font color=green>//и его ключ в res.</font color=green>
+
    '''return''' min                         <font color=green>// и выводим его.</font color=green>
    '''return''' *(Set.elements + key)
 
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.
Строка 70: Строка 94:
 
=== '''maximum''' ===
 
=== '''maximum''' ===
 
<code>
 
<code>
  '''T''' maximum(Set):
+
  '''T''' maximum(set<T> s):
     '''T''' max = Set.elements[0]              <font color=green>//Принимаем первый элемент множества за максимальный.</font color=green>
+
     '''T''' max = s.elements[0]              <font color=green>// Принимаем первый элемент множества за максимальный.</font color=green>
     '''int''' res = 0
+
     '''int''' i
     '''for''' i = 1 '''to''' Set.n - 1
+
     '''for''' i = 1 '''to''' s.n - 1
         '''if''' max < Set.elements[i]          <font color=green>//Если есть элементы больше max,</font color=green>
+
         '''if''' max < s.elements[i]          <font color=green>// Ищем максимальный элемент множества</font color=green>
             max = Set.elements[i]         <font color=green>//то записывает элемент в max</font color=green>
+
             max = s.elements[i]
            res = i                      <font color=green>//и его ключ в res.</font color=green>
+
    '''return''' max                         <font color=green>// и выводим его.</font color=green>
    '''return''' *(Set.elements + key)
 
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.
Строка 84: Строка 107:
 
=== '''predecessor''' ===
 
=== '''predecessor''' ===
 
<code>
 
<code>
  '''T''' predecessor(Set, elem):
+
  '''T''' predecessor(set<T> s, T elem):
     '''for''' i = 1 '''to''' Set.n - 1
+
    '''int''' i
         '''if''' elem == Set.elements[i]
+
     '''for''' i = 1 '''to''' s.n - 1
             '''return''' *(Set.elements + i - 1)
+
         '''if''' elem == s.elements[i]         <font color=green>// Если в массиве находим елемент elem,</font color=green>
     '''return''' ''null''
+
             '''return''' s.elements[i - 1]    <font color=green>// то выводим предшествующий ему элемент.</font color=green>
 +
     '''return''' ''null''                         <font color=green>// Иначе выводим ''null''.</font color=green>
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.
Строка 95: Строка 119:
 
=== '''successor''' ===
 
=== '''successor''' ===
 
<code>
 
<code>
  '''T''' successor(Set, elem):
+
  '''T''' successor(set<T> s, T elem):
     '''for''' i = 0 '''to''' Set.n - 2
+
    '''int''' i
         '''if''' elem == Set.elements[i]
+
     '''for''' i = 1 '''to''' s.n - 1
             '''return''' *(Set.elements + i + 1)
+
         '''if''' elem == s.elements[i]         <font color=green>// Если в массиве находим елемент elem,</font color=green>
     '''return''' ''null''
+
             '''return''' s.elements[i + 1]    <font color=green>// то выводим следующий за ним элемент.</font color=green>
 +
     '''return''' ''null''                         <font color=green>// Иначе выводим ''null''.</font color=green>
 
</code>
 
</code>
 
Время выполнения {{---}} <tex>O(n)</tex>.
 
Время выполнения {{---}} <tex>O(n)</tex>.
Строка 122: Строка 147:
 
* Александров П. С. Введение в теорию множеств и общую топологию. — М.: Наука, 1977. — 368 с.
 
* Александров П. С. Введение в теорию множеств и общую топологию. — М.: Наука, 1977. — 368 с.
 
* Н. К. Верещагин, А. Шень. Часть 1. Начала теории множеств // Лекции по математической логике и теории алгоритмов. — 2-е изд., испр. — М.: МЦНМО, 2002. — 128 с.
 
* Н. К. Верещагин, А. Шень. Часть 1. Начала теории множеств // Лекции по математической логике и теории алгоритмов. — 2-е изд., испр. — М.: МЦНМО, 2002. — 128 с.
 
== Ссылки ==
 
 
* [http://ru.wikipedia.org/wiki/Упорядоченное_множество Упорядоченное множество — Википедия]
 
* [http://ru.wikipedia.org/wiki/Упорядоченное_множество Упорядоченное множество — Википедия]
  

Версия 17:30, 14 июня 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]. Рассмотрим реализацию на примере следующего множества: {0, 2, 4, ..., 5, 3, 1}.

struct set<T>:
  int even                         // количество четных элементов множества
  int odd                          // количество нечетных элементов множества
  int n = even + odd               // общее количество элементов множества
  T[n] elements                    // массив элементов множества типа T

insert

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

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

delete

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

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


search

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

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


minimum

T minimum(set<T> s):
    T min = s.elements[0]               // Принимаем первый элемент множества за минимальный.
    int i
    for i = 1 to s.n - 1
        if min > s.elements[i]          // Ищем минимальный элемент множества
            min = s.elements[i]
    return min                          // и выводим его.

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


maximum

T maximum(set<T> s):
    T max = s.elements[0]               // Принимаем первый элемент множества за максимальный.
    int i
    for i = 1 to s.n - 1
        if max < s.elements[i]          // Ищем максимальный элемент множества
            max = s.elements[i]
    return max                          // и выводим его.

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


predecessor

T predecessor(set<T> s, T elem):
    int i
    for i = 1 to s.n - 1
        if elem == s.elements[i]         // Если в массиве находим елемент elem,
            return s.elements[i - 1]     // то выводим предшествующий ему элемент.
    return null                          // Иначе выводим null.

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


successor

T successor(set<T> s, T elem):
    int i
    for i = 1 to s.n - 1
        if elem == s.elements[i]         // Если в массиве находим елемент elem,
            return s.elements[i + 1]     // то выводим следующий за ним элемент.
    return null                          // Иначе выводим null.

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


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

Примеры

  • Простые примеры множеств:
    • {1, 2, 3, ...},
    • {..., 3, 2, 1},
    • {1, 3, 5, ..., 2, 4, 6, ...},
    • {1, 3, 5, ..., 6, 4, 2},
    • {..., 5, 3, 1, 2, 4, 6, ...},
    • {..., 5, 3, 1, ..., 6, 4, 2},
  • пустое множество [math] \varnothing [/math],
  • множество натуральных чисел [math] \mathbb N [/math],
  • файлы в директории, отсортированные в алфавитном порядке.

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

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