1. 程式人生 > >數據結構-數據結構的擴展

數據結構-數據結構的擴展

item 之前 pan repl 維護 mark focus == pla

1 如何做數據擴張

4個步驟:

  1. 選擇一種基礎數據結構

  2. 確定基礎數據結構中要維護的附加信息

  3. 檢查基礎數據結構上一些操作是否需要維護附加信息

  4. 為附加信息添加一些新的操作

2 舉例

擴展紅黑樹(或是其他樹),能夠在O(lgn)內獲取第i小的元素.

為每個節點添加一個size成員變量,表示當前節點所有子節點的個數+1,加1是因為自己還有一個.因此:

pre->size=pre->left->size+pre->right->size+1;

要想找到第i小的元素

RBNode* RBTree::find(size_t i)
{
  return axu_find(mp_root,i);
}

RBNode* RBTree::aux_find(RBNode* cur,size_t i)
{
  size_t index = cur->left->size+1;//當前節點在書中的序號,秩
  if(index==i)
  {
    return cur;
  }else if(index < i){ //i還有在 cur 的後面
	return aux_find(cur->right,i-r);// i-r 表示,之前已經有r個了,再往後找i-r個就是了
  }else if(index > i){ // i 在 cur 的前面
    return aux_find(cur->left);  // 沒有跳過任何元素,因此直接傳 i
  }
}

相對應的,也可以找到第i大的元素,也就是根節點size-i+1小的元素.

確定一個節點在樹中的是第幾小的.

size_t* RBTree::find(RBNode *node)
{
  size_t index = node->left->size+1; // 這只是自己統治下節點的排序.
  RBNode* pre = node;
  while(pre != mp_root)
  {
    //只有自己是一個右節點的時候,才要加上左節點的元素數目,如果不是,就不加.
    if(pre == pre->p->right)
    {
      r=r+pre->p->left->size+1; //自己父節點的右子樹個數 + 父節點的1
    }
    pre = pre->p;
    //向上遞歸,直到p是根節點.
  }
}

size的維護

插入過程:

  • 添加元素時,所有元素途徑的路徑上 size+1,添加以後,自己的size=1,O(lgn)

  • 旋轉,以左旋為例: 原先父節點pre,旋轉以後父節點cur

    新的父節點的size等於原先父節點的size.(因為元素個數沒變)

    原先父節點的個數變為 pre->size=pre->left->size+cur->right->size+1

刪除過程:

  • 刪除操作,遍歷路徑從根節點到節點replace_node,路徑上所有節點size-1

  • 旋轉,同插入

數據結構-數據結構的擴展