Алгоритмы и структуры данных меняющие современный Frontend

XBSoftware

Вопросы на сегодня:

  1. Для чего фронтенд программисту нужно знать структуры данных и алгоритмы?

Disclaimer

Структура данных — программная единица, позволяющая хранить и обрабатывать множество однотипных и/или логически связанных данных в вычислительной технике.

Wikipedia

Алгори́тм — набор инструкций, описывающих порядок действий исполнителя для достижения некоторого результата.

Wikipedia

Структуры данных помогают решать правильно и эффективно поставленные задачи, путем наилучшего представления информации под использующиеся алгоритмы.

Дашукевич Владимир

Дерево

Типы деревьев:

  1. Красно-чёрное дерево
  2. Куча
  3. Префиксное дерево
  4. B-дерево
  5. R-дерево
  6. АВЛ-дерево
  7. и другие

DOM дерево

Операция Сложность Метод
Добавление O(1) insertBefore, appendChild, append, prepend, after, before
Удаление O(1) removeChild, remove, replaceWith
Поиск O(1)/O(n) querySelector, querySelectorAll, getElementById, getElementsByClassName

Поиск по DOM дереву:

  1. Поиск в ширину
  2. Поиск в глубину

Поиск в ширину:

Поиск в глубину:

Изменения DOM

React/Preact/Inferno

Virtual DOM

Поиск отличий

Старое дерево Новое дерево
<li>Первый</li> <li>Первый</li>
<li>Второй</li> <li>Третий</li>
<li>Третий</li>  
Старое дерево Новое дерево
<li>Первый</li> <li>Первый</li>
<li>Второй</li> <li>Третий</li>
<li>Третий</li>  
Старое дерево Новое дерево Результат
<li>Первый</li> <li>Первый</li> <li>Первый</li>
<li>Второй</li> <li>Третий</li>  
<li>Третий</li>    
Старое дерево Новое дерево Результат
<li>Первый</li> <li>Первый</li> <li>Первый</li>
<li>Второй</li> <li>Третий</li> <li>Третий</li>
<li>Третий</li>    
Старое дерево Новое дерево Результат
<li>Первый</li> <li>Первый</li> <li>Первый</li>
<li>Второй</li> <li>Третий</li> <li>Третий</li>
<li>Третий</li>                        <li>Третий</li>
Старое дерево Новое дерево
<li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li>
<li key="key3">Третий</li>  
Старое дерево Новое дерево
<li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li>
<li key="key3">Третий</li>  
Старое дерево Новое дерево Результат
<li key="key1">Первый</li> <li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li> <li key="key2">Второй</li>
<li key="key3">Третий</li>   <li key="key3">Третий</li>

Хэш-таблица

Ключ Компонент
key1 <li key="key1">Первый</li>
key2 <li key="key2">Второй</li>
key3 <li key="key3">Третий</li>
Старое дерево Новое дерево Результат
<li key="key1">Первый</li> <li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li> <li key="key2">Второй</li>
<li key="key3">Третий</li>   <li key="key3">Третий</li>

Хэш-таблица

Ключ Компонент
key1 <li key="key1">Первый</li>
key2 <li key="key2">Второй</li>
key3 <li key="key3">Третий</li>
Старое дерево Новое дерево Результат
<li key="key1">Первый</li> <li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li> <li key="key2">Второй</li>
<li key="key3">Третий</li>   <li key="key3">Третий</li>

Хэш-таблица

Ключ Компонент
key1 <li key="key1">Первый</li>
key2 <li key="key2">Второй</li>
key3 <li key="key3">Третий</li>
Старое дерево Новое дерево Результат
<li key="key1">Первый</li> <li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li> <li key="key2">Второй</li>
<li key="key3">Третий</li>   <li key="key3">Третий</li>

Хэш-таблица

Ключ Компонент
key1 <li key="key1">Первый</li>
key2 <li key="key2">Второй</li>
key3 <li key="key3">Третий</li>
Старое дерево Новое дерево Результат
<li key="key1">Первый</li> <li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li> <li key="key3">Третий</li>
<li key="key3">Третий</li>   <li key="key2">Второй</li>

Хэш-таблица

Ключ Компонент
key1 <li key="key1">Первый</li>
key2 <li key="key2">Второй</li>
key3 <li key="key3">Третий</li>
Старое дерево Новое дерево Результат
<li key="key1">Первый</li> <li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li> <li key="key3">Третий</li>
<li key="key3">Третий</li>   <li key="key2">Второй</li>

Хэш-таблица

Ключ Компонент
key1 <li key="key1">Первый</li>
key2 <li key="key2">Второй</li>
key3 <li key="key3">Третий</li>
Старое дерево Новое дерево Результат
<li key="key1">Первый</li> <li key="key1">Первый</li> <li key="key1">Первый</li>
<li key="key2">Второй</li> <li key="key3">Третий</li> <li key="key3">Третий</li>
<li key="key3">Третий</li>   <li key="key2">Второй</li>

Хэш-таблица

Ключ Компонент
key1 <li key="key1">Первый</li>
key2 <li key="key2">Второй</li>
key3 <li key="key3">Третий</li>

lit-html

lit-html

            const render = () => html`
              <ul>
                ${repeat(items, i => i.key, (i, index) => html`
                  <li>${index}: ${i.name}</li>`)}
              </ul>
            `;
        

Где ещё используются деревья:

  1. Специфические доменные области

Неизменяемые данные

            var arr = ["a", "b", "c", "z", "f", "k"];
            function render(items) {
               return arr
                  .map(item => `<div>${ item }</div>`)
                  .join(", ");
            }
            nav.innerHTML = render(arr.sort());
            div.innerHTML = render(arr);
        
            var arr = ["a", "b", "c", "z", "f", "k"];
            function render(items) {
               return arr
                  .map(item => `<div>${ item }</div>`)
                  .join(", ");
            }
            nav.innerHTML = render(arr.sort());
            div.innerHTML = render(arr);
        
            var arr = ["a", "b", "c", "z", "f", "k"];
            function render(items) {
               return arr
                  .map(item => `<div>${ item }</div>`)
                  .join(", ");
            }
            nav.innerHTML = render(arr.slice().sort());
            div.innerHTML = render(arr);
        

Redux store

            {...state, first : {
            	...state.first,
            	second : {
            		...state.first.second,
            		[action.someId] : {
            			...state.first.second[action.someId],
            			fourth : action.someValue
            		}
            	}
            }}
        
            {...state, first : {
            	...state.first,
            	second : {
            		...state.first.second,
            		[action.someId] : {
            			...state.first.second[action.someId],
            			fourth : action.someValue
            		}
            	}
            }}
        
            [
                ...array.slice(0, action.index),
                action.item,
                ...array.slice(action.index)
            ]
        
            [
                ...array.slice(0, action.index),
                action.item,
                ...array.slice(action.index)
            ]
        
Операция Сложность
Добавление элемента О(n)
Удаление элемента О(n)
Поиск О(1)/О(n)

Эффективна ли неизменяемость?

Крис Окасаки

Чисто функциональные структуры данных

Деревья

Map/List

Префиксное дерево (Trie tree)

Операция Сложность
Поиск О(|Key|)
Добавление элемента О(|Key|)
Удаление элемента О(|Key|)
Изменение О(|Key|)

Hash Array Mapped Trie (HAMT)

Immutability в JS

Immutability в JS

  1. ImmutableJS
  2. Seamless-immutable
  3. Mori.js

ImmutableJS

List в ImmutableJS

            const originalList = List([ 0 ]);
            // List [ 0 ]
            const newList = originalList.set(1, 1);
            // List [ 0, 1 ]
            const newList2 = originalList.set(0, 'overwritten');
            // List [ "overwritten" ]
            originalList.get(0);
            // "overwritten"
        

List в ImmutableJS

  1. До 32 элементов - обычный массив

Map в ImmutableJS

            const originalMap = Map({ a: 1 });
            // Map { a: 1 }
            const newMap = originalMap.set("b", 1);
            // Map { a: 1, b: 1 }
            const newMap2 = originalMap.set(a, 'overwritten');
            // Map { a: 'overwritten' }
            originalMap.get(a, 'overwritten');
            // 'overwritten'
        

Map в ImmutableJS

  1. До 8 элементов - обычный массив [[ключ, значение], ...]

HAMT в ImmutableJS

Очередь и стек

React Fiber

Перестроение DOM в React Fiber

  1. Построение/сравнение VDOM
  2. Применение изменений

Приоритеты React Fiber

  1. Синхронные операции
  2. Задачи для следующего такта
  3. Анимации
  4. Высокоприоритетные
  5. Низкоприоритетные
  6. Задачи на изменения вне экрана

Структуры данных в React Fiber

  1. Стек
  2. Очередь с приоритетами

Стек на массиве

Операция Сложность
Добавление элемента О(1)
Удаление элемента О(1)

Очередь на связанном списке

Операция Сложность
Добавление элемента О(1)
Удаление элемента О(1)

Очередь с приоритетами

Очередь с приоритетами

Операция/Сложность Массив Сорт. массив Связанный список
Добавление элемента О(1) О(n) О(n)
Получение элемента О(n) О(1) О(1)

Куча

Кучи

  1. Двоичная куча
  2. Биномиальная куча
  3. Фибоначчиева куча
  4. Тонкая куча
  5. Толстая куча
  6. и другие

Двоичная куча для максимума

  1. Значение в любой вершине не меньше, чем значения её потомков
  2. На i-ом слое 2^i вершин, кроме последнего.
  3. Последний слой заполнен слева направо

Изменения очереди

Очередь на двоичной куче

Операция Сложность
Добавление элемента О(log n)
Получение элемента О(log n)
Поиск макс. элемента О(1)

Что использует React Fiber?

Связанный список

Очередь с приоритетами

Операция/Сложность Куча Связанный список
Добавление элемента О(log n) О(n)
Получение элемента О(log n) О(1)
Поиск макс. элемента О(1) О(1)

Выводы

  1. Интересуйтесь структурами данных и соответствующими им алгоритмами

Вопросы на сегодня:

  1. Для чего фронтенд программисту нужно знать структуры данных и алгоритмы?

Для отрисовки форм на любом фреймворке или написания алгоритма валидации данных не нужны знания о структурах данных, но для действительно серьезных и сложных задач эти знания необходимы.

Дашукевич Владимир

Раунд!

Facebook: dashukevich.vova
Twitter: life__777