1. 程式人生 > >平衡二叉樹總結四:替罪羊樹(scapegoat tree)

平衡二叉樹總結四:替罪羊樹(scapegoat tree)

  之前在查treap樹的時候,偶然在知乎看到一篇比treap樹還簡單的替罪羊樹的介紹,傳送門:https://zhuanlan.zhihu.com/p/21263304,大神還是寫的很好的,有興趣的可以去看下,當然也可以看我的總結。

一 、平衡條件

  左子樹大小 < alpha * 根大小 並且 右子樹大小 < alpha * 根大小

 二、 替罪羊樹總結起來就兩個操作:

  1.拉平,當樹不滿足平衡條件時,把樹伸展成連結串列。

  2.重構,遞迴的選取連結串列的中點作為根節點重建平衡樹,這樣得到的幾乎是完美的平衡二叉樹。

三、基本操作

  0.結構

struct scapegoat{
  scapegoat* left;
  scapegoat* right;
  int val,size;
  bool real;
  scapegoat(int v,int s,bool r):val(v),size(s),real(r){left = right = NULL;}
};


  1.插入

  先正常的插入到二叉搜尋樹中,再回溯的過程中,判斷是否違背了平衡條件,如果違背了,拉平並重構該樹。

tree insert(tree t,int val){
  if(t==NULL){
    t = new scapegoat(val,1,1);
    return t;
  }
  bool r = 0;(t->size)++;
  if(val > t->val){
    t->right = insert(t->right,val);
    if(t->right->size > alpha*t->size+10){r=1;}
  }
  else if(val < t->val){
    t->left = insert(t->left,val);
    if(t->left->size > alpha*t->size+10){r=1;}
  }
  if(r){
    qu.clear();tree2list(t);
    t = rebuild(0,qu.size()-1);
  }
  return t;
}


  2.刪除

  採用lazy刪除,刪除的給打上一個標記,每次重構都把lazy點刪掉。

bool remove(tree t,int val){
  if(t==NULL)return 0;
  bool c;
  if(val>t->val)c = remove(t->right,val);
  else if(val<t->val)c = remove(t->left,val);
  else{
    if(t->real){t->real=0;c=1;}
    else{c=0;}
  }
  if(c)(t->size)--;
  return c;
}

3.總結

  總體來說思想很簡單,不過程式設計還是有一定複雜度的,更treap樹差不太多,效能的話據說是平均O(log(n))的,不過我的程式碼貌似重構的很頻繁,不知道是不是寫錯了。

  現在研究的不深,之後有機會再補充。 

#include<iostream>
#include<vector>
#include<queue>
using namespace std;

struct scapegoat{
  scapegoat* left;
  scapegoat* right;
  int val,size;//值域與儲存真實點個數的size域
  bool real;//該點是否是真實的
  scapegoat(int v,int s,bool r):val(v),size(s),real(r){left = right = NULL;}
}; 
typedef scapegoat* tree;
const int alpha = 0.55;//權重因子
vector<tree> qu;
void tree2list(tree t){//拉平樹
  if(t==NULL)return;
  if(t->left)tree2list(t->left);
  if(t->real)qu.push_back(t);
  if(t->right)tree2list(t->right);
  if(!t->real)delete t;
}

tree rebuild(int left,int right){//重構樹
  if(left > right)return NULL;
  int m = (left+right)/2;
  tree t = qu[m];
  t->size = right-left+1;
  t->left = rebuild(left,m-1);
  t->right = rebuild(m+1,right);
  return t;
}

tree insert(tree t,int val){
  if(t==NULL){
    t = new scapegoat(val,1,1);
    return t;
  }
  bool r = 0;(t->size)++;
  if(val > t->val){
    t->right = insert(t->right,val);
    if(t->right->size > alpha*t->size+10){r=1;}
  }
  else if(val < t->val){
    t->left = insert(t->left,val);
    if(t->left->size > alpha*t->size+10){r=1;}
  }
  if(r){
    cout << "dd" <<endl;
    qu.clear();tree2list(t);
    t = rebuild(0,qu.size()-1);
  }
  return t;
}

bool remove(tree t,int val){
  if(t==NULL)return 0;
  bool c;
  if(val>t->val)c = remove(t->right,val);
  else if(val<t->val)c = remove(t->left,val);
  else{
    if(t->real){t->real=0;c=1;}
    else{c=0;}
  }
  if(c)(t->size)--;
  return c;
}
void level(tree t){
  if(!t)return;
  tree now,last=t;
  queue<tree> qu1;
  qu1.push(t);
  while(qu1.size()){
    now = qu1.front();qu1.pop();
    if(now->left)qu1.push(now->left);
    if(now->right)qu1.push(now->right);
    cout << now->val << "(" << now->size << ")" << " ";
    if(now == last && qu1.size()){last = qu1.back();cout << endl;}
  }
  cout << endl;
}

int main(){
  int i;
  tree t=NULL;
  for(i=0;i<100;i++){
    t = insert(t,i);
  }
  level(t);
}


相關推薦

平衡總結替罪羊scapegoat tree

  之前在查treap樹的時候,偶然在知乎看到一篇比treap樹還簡單的替罪羊樹的介紹,傳送門:https://zhuanlan.zhihu.com/p/21263304,大神還是寫的很好的,有興趣的可以去看下,當然也可以看我的總結。 一 、平衡條件   左子樹大小 <

平衡總結treap

  類似avl樹的還有紅黑樹和伸展樹,然而程式設計確實很複雜,我先總結treap樹吧,比賽啥的也能用得上。從樹堆這個名字不難看出treap這種資料結構應該同時具有二叉搜尋樹與二叉堆的某些性質,實際上樹堆首先是一顆二叉搜尋樹,也就是說它滿足  left < root &

資料結構實現 6.1堆_基於動態陣列實現C++版

資料結構實現 6.1:二叉堆_基於動態陣列實現(C++版) 1. 概念及基本框架 1.1 滿二叉樹 1.2 完全二叉樹 2. 基本操作程式實現 2.1 增加操作 2.2 刪除操作 2.3 查詢操作

資料結構實驗之棧與佇列括號匹配SDUT 2134

#include <bits/stdc++.h> using namespace std; typedef long long ll; char s[100]; char a[100]; int main() { int i,j,k,f,top,len; while(

排序演算法()堆排序Heap Sort

堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。 基本思想: 堆的定義如下:具有n個元素的序列(k1,k2,...,kn),當且僅當滿足 時稱之為堆。由堆的定義可以看出,堆頂元素(即第一個元素)必為最小項(小頂堆)。 若以一維陣列儲存一個堆,則堆對應一棵完全二叉樹,且所有

實驗順序佇列迴圈佇列和鏈佇列

#ifndef CirQueue_H #define CirQueue_H const int QueueSize=100; //定義儲存佇列元素的陣列的最大長度 template //定義模板類CirQueue class CirQueue { publ

替罪羊Scapegoat Tree

package com.yc.tree; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; /** * @au

git操作之git branch本地倉庫

前面,介紹了git init/add/commit/restore/reset等git命令,今天介紹下git branch,這個命令是和分支相關的。首先要理解什麼是分支,簡單來說在協作開發中,每個人開發的功能都是不一樣的,每個人在開發的時候總是在自己的分支上進行開發,待測試正常後會把程式碼合併到一個穩定的分支

面試題平衡

depth 二叉樹 面試 true 思路 nod balance urn oot 題目描述:輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。 思路:利用上一題求二叉樹的深度 public class Solution { public boolean IsBalan

劍指offer第55.5平衡

題目描述 輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。 class Solution: def IsBalanced_Solution(self, pRoot): # write code here if not pRoot:

劍指offer系列的深度,平衡,陣列中只出現一次的數字

二叉樹的深度 題目描述 輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。 解題思路: 利用遞迴實現。如果一棵樹只有一個結點,那麼它的深度為1。遞迴的時候無需判斷左右子樹是否存在,因為如果該節點 為葉節點,它的左右

演算法題三十判斷是否是平衡

7. 判斷是否是BST 題目描述 輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。 分析 可以用遞迴的方法,從下向上遍歷各個結點(後序遍歷),如果結點是滿足BST的條件則返回該結點的高度,如果不滿足則直接停止遍歷並返回false。 程式碼 public cl

劍指offer輸入一棵,判斷該是否是平衡

輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。 //後續遍歷二叉樹,遍歷過程中求子樹高度,判斷是否平衡 class Solution { public: bool IsBalanced(TreeNode *root, int & dep){

劍指offer-39平衡

題目描述 輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。 思路 首先,什麼是平衡二叉樹?如果二叉樹中任意結點的左右子樹深度相差不超過1,那麼它就是平衡二叉樹。 最直接的做法,遍歷每個結點,藉助一個獲取樹深度的遞迴函式,根據該結點的左右子樹高度差判斷是否平衡,然後遞迴地對左右子樹進

資料結構實驗之查詢平衡 (SDUT 3374)

#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; int h; struct node *lc,*rc; //平衡二

面試題55平衡

一、題目 輸入一棵二叉樹的根結點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意結點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。 二、關鍵 三、解釋 四、程式碼 #include <cstdio> #include "..\Utilities\

#資料結構與演算法學習筆記#劍指Offer35是否平衡/AVL + 測試用例Java、C/C++

2018.11.3 前幾天有用遞迴實現了二叉樹的深度#資料結構與演算法學習筆記#劍指Offer36:二叉樹的深度(Java),因此可以對每個結點先序遍歷進行一次平衡驗證,只要確定每個結點都是平衡的

搜尋平衡,堆三者插入刪除操作分析總結

引言:搜尋二叉樹,平衡二叉樹,堆三者插入刪除操作在選擇題中經常出現,很容易混淆 所以在這裡就簡單總結一下: 一.搜尋二叉樹 定義:二叉查詢樹(Binary Search Tree),(又:二叉搜尋樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子

AVL平衡總結

我個人是通過b站學習的懂得 b站視訊連線: https://www.bilibili.com/video/av37955102?from=search&seid=14638889623357631324 https://www.bilibili.com/video/av379

簡直off 平衡

文章目錄 前言 題目 思路 暴力揭發 優化,從下往上的 前言 最近有道雲筆記老是沒響應,會員也這樣,所以把演算法的筆記公開到這個csdn,也算是公開的鞭策。 題目常練習起點位置: https://www.nowcod