簡體   English   中英

如何在O(N)時間構建二叉樹?

[英]How to build a binary tree in O(N ) time?

從上一個問題開始,我很想知道如何從N個未排序的大整數數組中按N次構建一個二叉樹?

除非列表中有一些前提條件可以讓您在恆定時間內計算每個項目在樹中的位置,否則無法“構建”(即按O(N)時間順序地將項目插入樹中) 。 每次插入最多要比較Log M次,其中M是樹中已有的項目數。

我同意這在一般的似乎是不可能的(假設我們有N項一般,全序集合S。)下面是一個非正式的說法,我本質上降低BST建設S上分選S的問題。

非正式論點。 SN個元素的集合。 現在構造一個二叉搜索樹T ,該樹存儲O(N)時間中來自S的項。

現在,對樹進行有序的行走,並在您訪問葉子時打印葉子的值。 您實質上是對S中的元素進行了排序。 這花了您O(| T |)個步驟,其中| T | 是樹的大小(即節點數)。 (在最壞的情況下,BST的大小為O(N log N) 。)

如果| T | = o(N log N),那么您就可以在o(N log N)時間內解決一般的排序問題,這是一個矛盾。

好,只是為了完整性...問題中的二叉樹是從數組構建的,每個數組元素都有一個葉子。 它使它們保持原始索引順序, 而不是值順序,因此,它不能神奇地使您按線性時間對列表進行排序。 它還需要保持平衡。

要在線性時間內構建這樣的樹,您可以使用像這樣的簡單遞歸算法(使用基於0的索引):

//build a tree of elements [start, end) in array
//precondition: end > start
buildTree(int[] array, int start, int end)
{
    if (end-start > 1)
    {
        int mid = (start+end)>>1;
        left = buildTree(array, start, mid);
        right = buildTree(array, mid, end);
        return new InternalNode(left,right); 
    }
    else
    {
        return new LeafNode(array[start]);
    }
}

我有一個主意,怎么可能。

用RadixSort排序數組,這是O(N)。 之后,使用遞歸過程插入葉子,例如:

node *insert(int *array, int size) {
  if(size <= 0)
     return NULL;
  node *rc = new node;
  int midpoint = size / 2;
  rc->data = array[midpoint];
  rc->left  = insert(array, midpoint);
  rc->right = insert(array + midpoint + 1, size - midpoint - 1);
  return rc;
}

由於我們不從上到下迭代樹,而是始終將節點附加到當前葉子,因此這也是O(1)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM