2008-09-29 96 views
18

我有一個數百萬數組的數組。查找數組數組中最大差異的算法

double* const data = new double (3600000); 

我需要遍歷數組並找到範圍(數組中的最大值減去最小值)。但是,有一個問題。我只想找到最小值和最大值相差1000個範圍內的範圍。

所以,我需要找到最大的:範圍(數據+ 0,+數據1000),範圍(數據+ 1,+數據1001),範圍(數據+ 2,數據+ 1002),.... ,範圍(數據+ 3599000,數據+ 3600000)。

我希望這是有道理的。基本上我可以像上面那樣做,但如果存在的話,我正在尋找更高效的算法。我認爲上述算法是O(n),但我覺得可以優化。我正在玩的一個想法是跟蹤最近的最大值和最小值,以及它們返回的距離,然後在必要時僅回溯。

我會在C++中被編碼的這一點,但一個不錯的算法僞代碼會就好了。另外,如果我試圖找到這個號碼有一個名字,我很想知道它是什麼。

謝謝。

+1

更合適,你的算法是O(O * m),其中m爲你正在尋找的範圍的大小。 – 2008-10-03 22:09:43

回答

8

您所描述的算法是真的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) 

我相信它應該會更快,因爲不斷的要低得多。

+0

我認爲在實踐中,這不會比簡單的方法更快,因爲您正在將複雜性轉移到操縱排序後的集合。如果設置的實現有任何內存分配,這將是一個很大的開銷。 – Skizz 2008-09-29 09:14:03

+0

人們如何提出這些巧妙的想法?我從來沒有想過使用一組來找到最大最小值。 無論如何,這看起來很簡單,你的解釋很棒。我會嘗試一下。 – Imbue 2008-09-29 09:18:53

+0

這個算法也是O(N),因爲一旦它保存了1,000個項目,維持該集合的時間應該是恆定的。我將成爲今日比較天真解決方案的基準。 – Imbue 2008-09-29 18:15:49

10

這種類型的問題屬於算法稱作流算法的一個分支。對問題的研究不僅需要O(n)解決方案,還需要在數據上一次性工作。數據作爲流輸入到算法中,算法不能保存所有數據,然後永久丟失。該算法需要得到關於數據的一些答案,例如最小值或中值。

具體來說,你正在尋找一個最大(或更通常地在文獻 - 最小值)在窗口上的流。

Here's a presentationarticle提到這個問題作爲他們試圖得到什麼的子問題。它可能會給你一些想法。

我認爲溶液的輪廓類似的東西 - 保持在其中在每一步驟的一個元件被插入到窗口和一個從所述另一側除去流的窗口(滑動窗口)。您實際存儲在內存中的項目並非全部是窗口中的1000個項目,而是選定的代表,這些代表將成爲最小(或最大)的最佳候選人。

閱讀文章。它有點複雜,但是在2-3次讀取之後,您可以獲得它的掛起。

6

這是一個很好的應用最小隊列 - 一個隊列(先進先出= FIFO),它可以同時跟蹤它包含的最小元素,以分期固定的時間更新。當然,最大隊列基本上是一樣的。

一旦你有了這個數據結構,你可以考慮CurrentMax(過去的1000個元素)減去CurrentMin,將它存儲爲BestSoFar,然後推新值並彈出舊值,然後再次檢查。通過這種方式,不斷更新BestSoFar,直到最終值成爲您問題的解決方案。每個單獨的步驟需要分攤不變的時間,所以整個事情是線性的,我知道的實現具有很好的標量常量(它很快)。

我不知道有關最小隊列的任何文檔 - 這是我與同事合作提出的數據結構。您可以通過內部跟蹤數據的每個連續子序列中最少元素的二叉樹來實現它。它簡化了只會從結構的一端彈出數據的問題。

如果您有興趣瞭解更多詳情,我可以嘗試提供。我正在考慮把這個數據結構寫成arxiv的文件。還要注意的是,Tarjan和其他人之前已經到過一個更強大的min-deque結構,可以在這裏工作,但實現更復雜。您可以通過google for "mindeque"瞭解Tarjan等人的工作。算法的

0

點子:

取數據的第一1000個值和對它們進行排序
最後在排序 - 首先是範圍(數據+ 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
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
  1. 在前1000個數字中讀取。
  2. 創建一個1000元素鏈表,跟蹤當前的1000個數字。
  3. 創建一個1000元素的指向鏈表節點的指針數組,1-1映射。
  4. 根據鏈接列表節點的值對指針數組進行排序。這將重新排列數組,但保持鏈接列表不變。
  5. 您現在可以通過檢查指針數組的第一個和最後一個元素來計算前1000個數字的範圍。
  6. 刪除第一個插入的元素,它是頭部還是尾部,具體取決於您如何創建鏈接列表。使用節點的值在指針數組上執行二進制搜索以找到將被除去的節點的指針,並將該數組移除以將其移除。
  7. 將第1001個元素添加到鏈接列表中,並通過執行插入排序的一個步驟將指針插入數組中的正確位置。這將保持數組排序。
  8. 現在你有分鐘。和最大。數值介於1和1001之間,可以使用指針數組的第一個和最後一個元素來計算範圍。
  9. 現在應該明白你需要爲數組的其餘部分做些什麼。

該算法應該是O(n),因爲刪除和插入以log(1e3)爲界限,其他所有操作都需要一定的時間。

0

我決定看看我能想到解決這個問題的最有效的算法是使用實​​際的代碼和實際的時間。我首先創建了一個簡單的解決方案,使用循環緩衝區跟蹤前n個條目的最小/最大值,並使用測試工具來測量速度。在簡單的解決方案中,將每個數據值與最小/最大值的集合進行比較,這是關於window_size * count測試(其中原始問題中的窗口大小爲1000,計數爲3600000)。

然後我想了想如何讓它更快。首先,我創建了一個解決方案,使用fifo隊列存儲window_size值和鏈接列表,以便按升序存儲值,其中鏈接列表中的每個節點也是隊列中的節點。爲了處理數據值,將fifo末尾的項目從鏈接列表和隊列中移除。新的值被添加到隊列的開始,並且使用線性搜索來查找鏈接列表中的位置。然後可以從鏈表的開始和結束讀取最小值和最大值。這很快,但隨着window_size的增加(即線性),不能很好地擴展。

所以我決定在系統中添加一個二叉樹來加速算法的搜索部分。 window_size = 1000和count = 3600000的最終計時是:

Simple: 106875 
Quite Complex: 1218 
Complex: 1219 

這是預期的和意外的。預計使用排序鏈接列表會有所幫助,但意想不到的是,擁有自我平衡樹的開銷並未抵消更快搜索的優勢。我嘗試了後兩種方法,增加了窗口大小,發現它們總是幾乎相同,達到100000的window_size。

這一切都表明理論算法是一回事,實現它們是另一回事。

不管怎麼說,對於那些有興趣,這裏是我寫的代碼(有相當多的!):

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; 
} 
相關問題