Алгоритм для нахождения максимальной разницы в массиве чисел

Один из возможных способов - объявить файл "apiUrl: ' http: // localhost: 4000 '" inside "environment.ts" следующим образом:

export const environment = {
  production: false,
  apiUrl: 'http://localhost:4000'
};

Файл находится под вашим проектом: "src / environment / environment.ts". Существует также версия Prod.

Получите доступ к значению в вашем коде следующим образом:

import { environment } from '../environments/environment';

Затем в вашем классе (app.component.ts):

  constructor() {
    console.log('config.apiUrl', environment.apiUrl);
  }

18
задан Imbue 29 September 2008 в 08:55
поделиться

7 ответов

Алгоритм, который Вы описываете, действительно O (N), но я думаю, что константа слишком высока. Другое решение, которое выглядит разумным, состоит в том, чтобы использовать O (N*log (N)) алгоритм следующий путь:

* create sorted container (std::multiset) of first 1000 numbers
* in loop (j=1, j<(3600000-1000); ++j)
   - calculate range
   - remove from the set number which is now irrelevant (i.e. in index *j - 1* of the array)
   - add to set new relevant number  (i.e. in index *j+1000-1* of the array)

я полагаю, что это должно быть быстрее, потому что константа намного ниже.

8
ответ дан 30 November 2019 в 08:38
поделиться

Идея алгоритма:

Принимают первые 1 000 значений данных и сортируют их
последнее в виде - первым является диапазон (данные + 0, данные + 999).
Затем удаляют из вида, заваливают первый элемент данными значения [0]
и добавляют данные элемента [1000]
Теперь, последнее в виде - первым является диапазон (данные + 1, данные + 1000).
Повторение, пока не сделано

// This should run in (DATA_LEN - RANGE_WIDTH)log(RANGE_WIDTH)
#include <set>
#include <algorithm>
using namespace std;

const int DATA_LEN = 3600000;
double* const data = new double (DATA_LEN);

....
....

const int RANGE_WIDTH = 1000;
double range = new double(DATA_LEN - RANGE_WIDTH);
multiset<double> data_set;
data_set.insert(data[i], data[RANGE_WIDTH]);

for (int i = 0 ; i < DATA_LEN - RANGE_WIDTH - 1 ; i++)
{
   range[i] = *data_set.end() - *data_set.begin();
   multiset<double>::iterator iter = data_set.find(data[i]);
   data_set.erase(iter);
   data_set.insert(data[i+1]);
}
range[i] = *data_set.end() - *data_set.begin();

// range now holds the values you seek

необходимо, вероятно, проверить это на прочь 1 ошибкой, но идея там.

0
ответ дан 30 November 2019 в 08:38
поделиться

Этот тип вопроса принадлежит ответвлению алгоритмов, названных, передавая алгоритмы потоком. Это - исследование проблем, которые требуют не только O (n) решение, но также и потребность работать в единственной передаче по данным. данные введены как поток к алгоритму, алгоритм не может сохранить все данные и затем и затем это потеряно навсегда. алгоритм должен получить некоторый ответ о данных, такой что касается экземпляра минимум или медиана.

Конкретно Вы ищете максимум (или чаще всего в литературе - минимум) в окне по потоку.

Вот презентация на статья , которая упоминает эту проблему как sub проблему того, что они пытаются достигнуть. это могло бы дать Вам некоторое представление.

я думаю, что схема решения - что-то как этот - поддерживают окно по потоку, где на каждом шаге один элемент вставляется в окно, и каждый удален из другой стороны (раздвижное окно). Объекты, которые Вы на самом деле сохраняете в памяти, не являются всеми этими 1 000 объектов в окне, но выбранные представители, которые собираются быть хорошими кандидатами на то, чтобы быть минимумом (или максимум).

читает статью. это немного сложно, но после 2-3 чтений можно приобрести навык его.

10
ответ дан 30 November 2019 в 08:38
поделиться

Это - хорошее приложение минимальная очередь - очередь (Метод "первым пришел - первым вышел" = FIFO), который может одновременно отслеживать минимальный элемент, который это содержит с амортизируемыми постоянно-разовыми обновлениями. Конечно, макс. очередь является в основном тем же самым.

, После того как Вы имеете в распоряжении эту структуру данных, можно рассмотреть CurrentMax (прошлых 1 000 элементов) минус CurrentMin, хранилище что как BestSoFar, и затем продвигать новое значение и выталкивать старое значение и проверять снова. Таким образом продолжайте обновлять BestSoFar, пока окончательное значение не будет решением Вашего вопроса. У каждого одноэтапные взятия амортизировали постоянное время, таким образом, все это линейно, и реализация, о которой я знаю, есть хорошая скалярная константа (это быстро).

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

, Если Вам интересно более подробно, я могу попытаться обеспечить их. Я думал об описывании этой структуры данных как статья для arxiv. Также обратите внимание, что Тарьян и другие ранее прибыли в более мощную структуру минимальной двухсторонней очереди, которая будет работать здесь, но реализация намного более сложна. Вы можете , Google для "mindeque" для чтения о Тарьяне и др. работает.

6
ответ дан 30 November 2019 в 08:38
поделиться
std::multiset<double> range;
double currentmax = 0.0;
for (int i = 0;  i < 3600000;  ++i)
{
    if (i >= 1000)
        range.erase(range.find(data[i-1000]));
    range.insert(data[i]);
    if (i >= 999)
        currentmax = max(currentmax, *range.rbegin());
}

Примечание непротестированный код.

Редактирование: зафиксированная ошибка диапазона.

0
ответ дан 30 November 2019 в 08:38
поделиться
  1. чтение в первых 1 000 чисел.
  2. создают 1 000 связанных списков элемента, которые отслеживают текущие 1 000 чисел.
  3. создают 1 000 массивов элемента указателей на узлы связанного списка, отображение 1-1.
  4. сортируют массив указателей на основе значений узла связанного списка. Это перестроит массив, но сохранит связанный список в целости.
  5. можно теперь вычислить диапазон для первых 1 000 чисел путем исследования первого и последнего элемента массива указателей.
  6. удаляют первый вставленный элемент, который является или головой или хвостом в зависимости от того, как Вы сделали свой связанный список. Используя значение узла выполняют двоичный поиск на массиве указателей, чтобы найти указатель удаленного будущим образом узла и сместить массив один для удаления его.
  7. добавляют 1001-й элемент к связанному списку и вставляют указатель на него в правильном положении в массиве, путем выполнения одного шага вида вставки. Это сохранит массив отсортированным.
  8. теперь Вы имеете минуту и максимум значение чисел между 1 и 1001, и можете вычислить диапазон с помощью первого и последнего элемента массива указателей.
  9. должно теперь быть очевидно, что необходимо сделать для остальной части массива.

алгоритм должен быть O (n) начиная с удаления, и вставка ограничена журналом (1e3), и все остальное занимает время.

0
ответ дан 30 November 2019 в 08:38
поделиться

Я решил видеть то, о чем самом эффективном алгоритме я мог думать для решения этой проблемы, использовал фактический код и фактические синхронизации. Я сначала создал простое решение, то, которое отслеживает минуту / макс. для предыдущих n записей с помощью кольцевого буфера и тестовой обвязки для измерения скорости. В простом решении каждое значение данных сравнено со множеством минимальных значений / макс. значений, таким образом, это о window_size * тесты количества (где размер окна в исходном вопросе 1000, и количество 3600000).

я затем думал о том, как сделать его быстрее. Прежде всего я создал решение, которое использовало очередь FIFO для хранения значений window_size и связанного списка для хранения значений в порядке возрастания, где каждый узел в связанном списке был также узлом в очереди. Для обработки значения данных объект в конце FIFO был удален из связанного списка и очереди. Новое значение было добавлено к запуску очереди, и линейный поиск использовался для нахождения положения в связанном списке. Минута и макс. значения могли затем быть считаны из запуска и конца связанного списка. Это было быстро, но не масштабируется хорошо с увеличением window_size (т.е. линейно).

, Таким образом, я решил добавить двоичное дерево к системе, чтобы попытаться ускорить поисковую часть алгоритма. Заключительные синхронизации для window_size = 1000 и количество = 3600000 были:

Simple: 106875
Quite Complex: 1218
Complex: 1219

, который и ожидался и неожидан. Ожидаемый в том использовании отсортированного связанного списка помог, неожиданный в этом издержки наличия сам, балансирующееся дерево не смещало преимущество более быстрого поиска. Я попробовал последние два увеличенным размером окна и нашел что всегда почти идентичного до window_size 100 000.

то, Которое все идет, чтобы показать, что теоретизирование об алгоритмах является одной вещью, реализовывая их, является чем-то еще.

Так или иначе, для тех, которым интересно, вот код, который я написал (существует вполне немного!):

Range.h:

#include <algorithm>
#include <iostream>
#include <ctime>

using namespace std;

//  Callback types.
typedef void (*OutputCallback) (int min, int max);
typedef int (*GeneratorCallback) ();

//  Declarations of the test functions.
clock_t Simple (int, int, GeneratorCallback, OutputCallback);
clock_t QuiteComplex (int, int, GeneratorCallback, OutputCallback);
clock_t Complex (int, int, GeneratorCallback, OutputCallback);

main.cpp:

#include "Range.h"

int
  checksum;

//  This callback is used to get data.
int CreateData ()
{
  return rand ();
}

//  This callback is used to output the results.
void OutputResults (int min, int max)
{
  //cout << min << " - " << max << endl;
  checksum += max - min;
}

//  The program entry point.
void main ()
{
  int
    count = 3600000,
    window = 1000;

  srand (0);
  checksum = 0;
  std::cout << "Simple: Ticks = " << Simple (count, window, CreateData, OutputResults) << ", checksum = " << checksum << std::endl;
  srand (0);
  checksum = 0;
  std::cout << "Quite Complex: Ticks = " << QuiteComplex (count, window, CreateData, OutputResults) << ", checksum = " << checksum << std::endl;
  srand (0);
  checksum = 0;
  std::cout << "Complex: Ticks = " << Complex (count, window, CreateData, OutputResults) << ", checksum = " << checksum << std::endl;
}

Simple.cpp:

#include "Range.h"

//  Function to actually process the data.
//  A circular buffer of min/max values for the current window is filled
//  and once full, the oldest min/max pair is sent to the output callback
//  and replaced with the newest input value. Each value inputted is 
//  compared against all min/max pairs.
void ProcessData
(
  int count,
  int window,
  GeneratorCallback input,
  OutputCallback output,
  int *min_buffer,
  int *max_buffer
)
{
  int
    i;

  for (i = 0 ; i < window ; ++i)
  {
    int
      value = input ();

    min_buffer [i] = max_buffer [i] = value;

    for (int j = 0 ; j < i ; ++j)
    {
      min_buffer [j] = min (min_buffer [j], value);
      max_buffer [j] = max (max_buffer [j], value);
    }
  }

  for ( ; i < count ; ++i)
  {
    int
      index = i % window;

    output (min_buffer [index], max_buffer [index]);

    int
      value = input ();

    min_buffer [index] = max_buffer [index] = value;

    for (int k = (i + 1) % window ; k != index ; k = (k + 1) % window)
    {
      min_buffer [k] = min (min_buffer [k], value);
      max_buffer [k] = max (max_buffer [k], value);
    }
  }

  output (min_buffer [count % window], max_buffer [count % window]);
}

//  A simple method of calculating the results.
//  Memory management is done here outside of the timing portion.
clock_t Simple
(
  int count,
  int window,
  GeneratorCallback input,
  OutputCallback output
)
{
  int
    *min_buffer = new int [window],
    *max_buffer = new int [window];

  clock_t
    start = clock ();

  ProcessData (count, window, input, output, min_buffer, max_buffer);

  clock_t
    end = clock ();

  delete [] max_buffer;
  delete [] min_buffer;

  return end - start;
}

QuiteComplex.cpp:

#include "Range.h"

template <class T>
class Range
{
private:
  //  Class Types

  //  Node Data
  //  Stores a value and its position in various lists.
  struct Node
  {
    Node
      *m_queue_next,
      *m_list_greater,
      *m_list_lower;

    T
      m_value;
  };

public:
  //  Constructor
  //  Allocates memory for the node data and adds all the allocated
  //  nodes to the unused/free list of nodes.
  Range
  (
    int window_size
  ) :
    m_nodes (new Node [window_size]),
    m_queue_tail (m_nodes),
    m_queue_head (0),
    m_list_min (0),
    m_list_max (0),
    m_free_list (m_nodes)
  {
    for (int i = 0 ; i < window_size - 1 ; ++i)
    {
      m_nodes [i].m_list_lower = &m_nodes [i + 1];
    }

    m_nodes [window_size - 1].m_list_lower = 0;
  }

  //  Destructor
  //  Tidy up allocated data.
  ~Range ()
  {
    delete [] m_nodes;
  }

  //  Function to add a new value into the data structure.
  void AddValue
  (
    T value
  )
  {
    Node
      *node = GetNode ();

    //  clear links
    node->m_queue_next = 0;

    //  set value of node
    node->m_value = value;

    //  find place to add node into linked list
    Node
      *search;

    for (search = m_list_max ; search ; search = search->m_list_lower)
    {
      if (search->m_value < value)
      {
        if (search->m_list_greater)
        {
          node->m_list_greater = search->m_list_greater;
          search->m_list_greater->m_list_lower = node;
        }
        else
        {
          m_list_max = node;
        }

        node->m_list_lower = search;
        search->m_list_greater = node;
      }
    }

    if (!search)
    {
      m_list_min->m_list_lower = node;
      node->m_list_greater = m_list_min;
      m_list_min = node;
    }
  }

  //  Accessor to determine if the first output value is ready for use.
  bool RangeAvailable ()
  {
    return !m_free_list;
  }

  //  Accessor to get the minimum value of all values in the current window.
  T Min ()
  {
    return m_list_min->m_value;
  }

  //  Accessor to get the maximum value of all values in the current window.
  T Max ()
  {
    return m_list_max->m_value;
  }

private:
  //  Function to get a node to store a value into.
  //  This function gets nodes from one of two places:
  //    1. From the unused/free list
  //    2. From the end of the fifo queue, this requires removing the node from the list and tree
  Node *GetNode ()
  {
    Node
      *node;

    if (m_free_list)
    {
      //  get new node from unused/free list and place at head
      node = m_free_list;

      m_free_list = node->m_list_lower;

      if (m_queue_head)
      {
        m_queue_head->m_queue_next = node;
      }

      m_queue_head = node;
    }
    else
    {
      //  get node from tail of queue and place at head
      node = m_queue_tail;

      m_queue_tail = node->m_queue_next;
      m_queue_head->m_queue_next = node;
      m_queue_head = node;

      //  remove node from linked list
      if (node->m_list_lower)
      {
        node->m_list_lower->m_list_greater = node->m_list_greater;
      }
      else
      {
        m_list_min = node->m_list_greater;
      }

      if (node->m_list_greater)
      {
        node->m_list_greater->m_list_lower = node->m_list_lower;
      }
      else
      {
        m_list_max = node->m_list_lower;
      }
    }

    return node;
  }

  //  Member Data.
  Node
    *m_nodes,
    *m_queue_tail,
    *m_queue_head,
    *m_list_min,
    *m_list_max,
    *m_free_list;
};

//  A reasonable complex but more efficent method of calculating the results.
//  Memory management is done here outside of the timing portion.
clock_t QuiteComplex
(
  int size,
  int window,
  GeneratorCallback input,
  OutputCallback output
)
{
  Range <int>
    range (window);

  clock_t
    start = clock ();

  for (int i = 0 ; i < size ; ++i)
  {   
    range.AddValue (input ());

    if (range.RangeAvailable ())
    {
      output (range.Min (), range.Max ());
    }
  }

  clock_t
    end = clock ();

  return end - start;
}

Complex.cpp:

#include "Range.h"

template <class T>
class Range
{
private:
  //  Class Types

  //  Red/Black tree node colours.
  enum NodeColour
  {
    Red,
    Black
  };

  //  Node Data
  //  Stores a value and its position in various lists and trees.
  struct Node
  {
    //  Function to get the sibling of a node.
    //  Because leaves are stored as null pointers, it must be possible
    //  to get the sibling of a null pointer. If the object is a null pointer
    //  then the parent pointer is used to determine the sibling.
    Node *Sibling
    (
      Node *parent
    )
    {
      Node
        *sibling;

      if (this)
      {
        sibling = m_tree_parent->m_tree_less == this ? m_tree_parent->m_tree_more : m_tree_parent->m_tree_less;
      }
      else
      {
        sibling = parent->m_tree_less ? parent->m_tree_less : parent->m_tree_more;
      }

      return sibling;
    }

    //  Node Members
    Node
      *m_queue_next,
      *m_tree_less,
      *m_tree_more,
      *m_tree_parent,
      *m_list_greater,
      *m_list_lower;

    NodeColour
      m_colour;

    T
      m_value;
  };

public:
  //  Constructor
  //  Allocates memory for the node data and adds all the allocated
  //  nodes to the unused/free list of nodes.
  Range
  (
    int window_size
  ) :
    m_nodes (new Node [window_size]),
    m_queue_tail (m_nodes),
    m_queue_head (0),
    m_tree_root (0),
    m_list_min (0),
    m_list_max (0),
    m_free_list (m_nodes)
  {
    for (int i = 0 ; i < window_size - 1 ; ++i)
    {
      m_nodes [i].m_list_lower = &m_nodes [i + 1];
    }

    m_nodes [window_size - 1].m_list_lower = 0;
  }

  //  Destructor
  //  Tidy up allocated data.
  ~Range ()
  {
    delete [] m_nodes;
  }

  //  Function to add a new value into the data structure.
  void AddValue
  (
    T value
  )
  {
    Node
      *node = GetNode ();

    //  clear links
    node->m_queue_next = node->m_tree_more = node->m_tree_less = node->m_tree_parent = 0;

    //  set value of node
    node->m_value = value;

    //  insert node into tree
    if (m_tree_root)
    {
      InsertNodeIntoTree (node);
      BalanceTreeAfterInsertion (node);
    }
    else
    {
      m_tree_root = m_list_max = m_list_min = node;
      node->m_tree_parent = node->m_list_greater = node->m_list_lower = 0;
    }

    m_tree_root->m_colour = Black;
  }

  //  Accessor to determine if the first output value is ready for use.
  bool RangeAvailable ()
  {
    return !m_free_list;
  }

  //  Accessor to get the minimum value of all values in the current window.
  T Min ()
  {
    return m_list_min->m_value;
  }

  //  Accessor to get the maximum value of all values in the current window.
  T Max ()
  {
    return m_list_max->m_value;
  }

private:
  //  Function to get a node to store a value into.
  //  This function gets nodes from one of two places:
  //    1. From the unused/free list
  //    2. From the end of the fifo queue, this requires removing the node from the list and tree
  Node *GetNode ()
  {
    Node
      *node;

    if (m_free_list)
    {
      //  get new node from unused/free list and place at head
      node = m_free_list;

      m_free_list = node->m_list_lower;

      if (m_queue_head)
      {
        m_queue_head->m_queue_next = node;
      }

      m_queue_head = node;
    }
    else
    {
      //  get node from tail of queue and place at head
      node = m_queue_tail;

      m_queue_tail = node->m_queue_next;
      m_queue_head->m_queue_next = node;
      m_queue_head = node;

      //  remove node from tree
      node = RemoveNodeFromTree (node);
      RebalanceTreeAfterDeletion (node);

      //  remove node from linked list
      if (node->m_list_lower)
      {
        node->m_list_lower->m_list_greater = node->m_list_greater;
      }
      else
      {
        m_list_min = node->m_list_greater;
      }

      if (node->m_list_greater)
      {
        node->m_list_greater->m_list_lower = node->m_list_lower;
      }
      else
      {
        m_list_max = node->m_list_lower;
      }
    }

    return node;
  }

  //  Rebalances the tree after insertion
  void BalanceTreeAfterInsertion
  (
    Node *node
  )
  {
    node->m_colour = Red;

    while (node != m_tree_root && node->m_tree_parent->m_colour == Red)
    {
      if (node->m_tree_parent == node->m_tree_parent->m_tree_parent->m_tree_more)
      {
        Node
          *uncle = node->m_tree_parent->m_tree_parent->m_tree_less;

        if (uncle && uncle->m_colour == Red)
        {
          node->m_tree_parent->m_colour = Black;
          uncle->m_colour = Black;
          node->m_tree_parent->m_tree_parent->m_colour = Red;
          node = node->m_tree_parent->m_tree_parent;
        }
        else
        {
          if (node == node->m_tree_parent->m_tree_less)
          {
            node = node->m_tree_parent;
            LeftRotate (node);
          }

          node->m_tree_parent->m_colour = Black;
          node->m_tree_parent->m_tree_parent->m_colour = Red;
          RightRotate (node->m_tree_parent->m_tree_parent);
        }
      }
      else
      {
        Node
          *uncle = node->m_tree_parent->m_tree_parent->m_tree_more;

        if (uncle && uncle->m_colour == Red)
        {
          node->m_tree_parent->m_colour = Black;
          uncle->m_colour = Black;
          node->m_tree_parent->m_tree_parent->m_colour = Red;
          node = node->m_tree_parent->m_tree_parent;
        }
        else
        {
          if (node == node->m_tree_parent->m_tree_more)
          {
            node = node->m_tree_parent;
            RightRotate (node);
          }

          node->m_tree_parent->m_colour = Black;
          node->m_tree_parent->m_tree_parent->m_colour = Red;
          LeftRotate (node->m_tree_parent->m_tree_parent);
        }
      }
    }
  }

  //  Adds a node into the tree and sorted linked list
  void InsertNodeIntoTree
  (
    Node *node
  )
  {
    Node
      *parent = 0,
      *child = m_tree_root;

    bool
      greater;

    while (child)
    {
      parent = child;
      child = (greater = node->m_value > child->m_value) ? child->m_tree_more : child->m_tree_less;
    }

    node->m_tree_parent = parent;

    if (greater)
    {
      parent->m_tree_more = node;

      //  insert node into linked list
      if (parent->m_list_greater)
      {
        parent->m_list_greater->m_list_lower = node;
      }
      else
      {
        m_list_max = node;
      }

      node->m_list_greater = parent->m_list_greater;
      node->m_list_lower = parent;
      parent->m_list_greater = node;
    }
    else
    {
      parent->m_tree_less = node;

      //  insert node into linked list
      if (parent->m_list_lower)
      {
        parent->m_list_lower->m_list_greater = node;
      }
      else
      {
        m_list_min = node;
      }

      node->m_list_lower = parent->m_list_lower;
      node->m_list_greater = parent;
      parent->m_list_lower = node;
    }
  }

  //  Red/Black tree manipulation routine, used for removing a node
  Node *RemoveNodeFromTree
  (
    Node *node
  )
  {
    if (node->m_tree_less && node->m_tree_more)
    {
      //  the complex case, swap node with a child node
      Node
        *child;

      if (node->m_tree_less)
      {
        // find largest value in lesser half (node with no greater pointer)
        for (child = node->m_tree_less ; child->m_tree_more ; child = child->m_tree_more)
        {
        }
      }
      else
      {
        // find smallest value in greater half (node with no lesser pointer)
        for (child = node->m_tree_more ; child->m_tree_less ; child = child->m_tree_less)
        {
        }
      }

      swap (child->m_colour, node->m_colour);

      if (child->m_tree_parent != node)
      {
        swap (child->m_tree_less, node->m_tree_less);
        swap (child->m_tree_more, node->m_tree_more);
        swap (child->m_tree_parent, node->m_tree_parent);

        if (!child->m_tree_parent)
        {
          m_tree_root = child;
        }
        else
        {
          if (child->m_tree_parent->m_tree_less == node)
          {
            child->m_tree_parent->m_tree_less = child;
          }
          else
          {
            child->m_tree_parent->m_tree_more = child;
          }
        }

        if (node->m_tree_parent->m_tree_less == child)
        {
          node->m_tree_parent->m_tree_less = node;
        }
        else
        {
          node->m_tree_parent->m_tree_more = node;
        }
      }
      else
      {
        child->m_tree_parent = node->m_tree_parent;
        node->m_tree_parent = child;

        Node
          *child_less = child->m_tree_less,
          *child_more = child->m_tree_more;

        if (node->m_tree_less == child)
        {
          child->m_tree_less = node;
          child->m_tree_more = node->m_tree_more;
          node->m_tree_less = child_less;
          node->m_tree_more = child_more;
        }
        else
        {
          child->m_tree_less = node->m_tree_less;
          child->m_tree_more = node;
          node->m_tree_less = child_less;
          node->m_tree_more = child_more;
        }

        if (!child->m_tree_parent)
        {
          m_tree_root = child;
        }
        else
        {
          if (child->m_tree_parent->m_tree_less == node)
          {
            child->m_tree_parent->m_tree_less = child;
          }
          else
          {
            child->m_tree_parent->m_tree_more = child;
          }
        }
      }

      if (child->m_tree_less)
      {
        child->m_tree_less->m_tree_parent = child;
      }

      if (child->m_tree_more)
      {
        child->m_tree_more->m_tree_parent = child;
      }

      if (node->m_tree_less)
      {
        node->m_tree_less->m_tree_parent = node;
      }

      if (node->m_tree_more)
      {
        node->m_tree_more->m_tree_parent = node;
      }
    }

    Node
      *child = node->m_tree_less ? node->m_tree_less : node->m_tree_more;

    if (node->m_tree_parent->m_tree_less == node)
    {
      node->m_tree_parent->m_tree_less = child;
    }
    else
    {
      node->m_tree_parent->m_tree_more = child;
    }

    if (child)
    {
      child->m_tree_parent = node->m_tree_parent;
    }

    return node;
  }

  //  Red/Black tree manipulation routine, used for rebalancing a tree after a deletion
  void RebalanceTreeAfterDeletion
  (
    Node *node
  )
  {
    Node
      *child = node->m_tree_less ? node->m_tree_less : node->m_tree_more;

    if (node->m_colour == Black)
    {
      if (child && child->m_colour == Red)
      {
        child->m_colour = Black;
      }
      else
      {
        Node
          *parent = node->m_tree_parent,
          *n = child;

        while (parent)
        {
          Node
            *sibling = n->Sibling (parent);

          if (sibling && sibling->m_colour == Red)
          {
            parent->m_colour = Red;
            sibling->m_colour = Black;

            if (n == parent->m_tree_more)
            {
              LeftRotate (parent);
            }
            else
            {
              RightRotate (parent);
            }
          }

          sibling = n->Sibling (parent);

          if (parent->m_colour == Black &&
            sibling->m_colour == Black &&
            (!sibling->m_tree_more || sibling->m_tree_more->m_colour == Black) &&
            (!sibling->m_tree_less || sibling->m_tree_less->m_colour == Black))
          {
            sibling->m_colour = Red;
            n = parent;
            parent = n->m_tree_parent;
            continue;
          }
          else
          {
            if (parent->m_colour == Red &&
              sibling->m_colour == Black &&
              (!sibling->m_tree_more || sibling->m_tree_more->m_colour == Black) &&
              (!sibling->m_tree_less || sibling->m_tree_less->m_colour == Black))
            {
              sibling->m_colour = Red;
              parent->m_colour = Black;
              break;
            }
            else
            {
              if (n == parent->m_tree_more &&
                sibling->m_colour == Black &&
                (sibling->m_tree_more && sibling->m_tree_more->m_colour == Red) &&
                (!sibling->m_tree_less || sibling->m_tree_less->m_colour == Black))
              {
                sibling->m_colour = Red;
                sibling->m_tree_more->m_colour = Black;
                RightRotate (sibling);
              }
              else
              {
                if (n == parent->m_tree_less &&
                  sibling->m_colour == Black &&
                  (!sibling->m_tree_more || sibling->m_tree_more->m_colour == Black) &&
                  (sibling->m_tree_less && sibling->m_tree_less->m_colour == Red))
                {
                  sibling->m_colour = Red;
                  sibling->m_tree_less->m_colour = Black;
                  LeftRotate (sibling);
                }
              }

              sibling = n->Sibling (parent);
              sibling->m_colour = parent->m_colour;
              parent->m_colour = Black;

              if (n == parent->m_tree_more)
              {
                sibling->m_tree_less->m_colour = Black;
                LeftRotate (parent);
              }
              else
              {
                sibling->m_tree_more->m_colour = Black;
                RightRotate (parent);
              }
              break;
            }
          }
        }
      }
    }
  }

  //  Red/Black tree manipulation routine, used for balancing the tree
  void LeftRotate
  (
    Node *node
  )
  {
    Node
      *less = node->m_tree_less;

    node->m_tree_less = less->m_tree_more;

    if (less->m_tree_more)
    {
      less->m_tree_more->m_tree_parent = node;
    }

    less->m_tree_parent = node->m_tree_parent;

    if (!node->m_tree_parent)
    {
      m_tree_root = less;
    }
    else
    {
      if (node == node->m_tree_parent->m_tree_more)
      {
        node->m_tree_parent->m_tree_more = less;
      }
      else
      {
        node->m_tree_parent->m_tree_less = less;
      }
    }

    less->m_tree_more = node;
    node->m_tree_parent = less;
  }

  //  Red/Black tree manipulation routine, used for balancing the tree
  void RightRotate
  (
    Node *node
  )
  {
    Node
      *more = node->m_tree_more;

    node->m_tree_more = more->m_tree_less;

    if (more->m_tree_less)
    {
      more->m_tree_less->m_tree_parent = node;
    }

    more->m_tree_parent = node->m_tree_parent;

    if (!node->m_tree_parent)
    {
      m_tree_root = more;
    }
    else
    {
      if (node == node->m_tree_parent->m_tree_less)
      {
        node->m_tree_parent->m_tree_less = more;
      }
      else
      {
        node->m_tree_parent->m_tree_more = more;
      }
    }

    more->m_tree_less = node;
    node->m_tree_parent = more;
  }

  //  Member Data.
  Node
    *m_nodes,
    *m_queue_tail,
    *m_queue_head,
    *m_tree_root,
    *m_list_min,
    *m_list_max,
    *m_free_list;
};

//  A complex but more efficent method of calculating the results.
//  Memory management is done here outside of the timing portion.
clock_t Complex
(
  int count,
  int window,
  GeneratorCallback input,
  OutputCallback output
)
{
  Range <int>
    range (window);

  clock_t
    start = clock ();

  for (int i = 0 ; i < count ; ++i)
  {   
    range.AddValue (input ());

    if (range.RangeAvailable ())
    {
      output (range.Min (), range.Max ());
    }
  }

  clock_t
    end = clock ();

  return end - start;
}
0
ответ дан 30 November 2019 в 08:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: