二叉查詢樹(binary search tree),(又:二叉搜尋樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別為二叉排序樹。平均情況下插入查詢刪除元素是onlgn,最差情況下是on的
由二叉搜尋樹發展來的紅黑樹是set/map的底層容器,為了學習的梯度我們先基於二叉搜尋樹來完成set和map。
templatestruct bsnode
t data;
struct bsnode* parent;
struct bsnode* left;
struct bsnode* right;
};
templateclass bstree_base_iterator : public bidirectional_iterator
bstree_base_iterator(ptr p)
void increment()
if (pre == nullptr)
node = nullptr;
else
node = pre;
}else//下乙個結點是比自己大的結點(右子樹)中最小的(最左)
}void decrement()
if (pre == nullptr)
node = nullptr;
else
node = pre;
}else
}}; templateclass bstree_iterator //加一層封裝
bstree_iterator(ptr _p)
self& operator++(int)
self& operator--(int)
bool operator!=(const bstree_iterator& rhs)
bool operator==(const bstree_iterator& rhs)
t& operator*()
t& operator->()
};
插入刪除查詢元素都可以利用和節點的值進行比較來遞迴查詢,為了避免stackoverflow可以使用遞迴函式的非遞迴形式
templateclass bstree
node_ptr insert_aux(node_ptr p, node_ptr pre,const value_type& val, node_ptr& ret)
return new_node(val, pre);
/* 遞迴版本 數目太多會stackoverflow
if(!p)
if (p->data > val)
p->left = insert_aux(p->left, p, val, ret);
else if (p->data < val)
p->right = insert_aux(p->right, p, val, ret);
else
ret = p;
return p;*/
} iterator find_aux(node_ptr p, const value_type& val)
return iterator(p);
} void del()
if (p->right)
//刪除之前保證左右子樹入隊 否則會有記憶體洩露
delete p;
}node = nullptr;
} //刪除操作,分四種情況
//1. 左右子樹為空,刪除結點 並且將其父節點對應指標設定為空即可
//2. 左子樹空 右不空 刪除結點 並且將其父節點對應指標設定為右子樹即可
//3. 左不空 右空 刪除結點 並且將其父節點對應指標設定為左子樹即可
//4. 左右不空 找到左子樹中值最大的元素 和結點元素交換
void erase_aux(node_ptr p)
else if (p->parent->left!=nullptr && p->parent->left->data == p->data)
p->parent->left = nullptr;
else if (p->parent->right!=nullptr && p->parent->right->data == p->data)
p->parent->right = nullptr;
delete(p);
}else if (p->left == nullptr&&p->right != nullptr)
else if (p->parent->left!=nullptr && p->parent->left->data == p->data)
p->parent->left = p->right, p->right->parent = p->parent;
else if (p->parent->right!=nullptr && p->parent->right->data == p->data)
p->parent->right = p->right, p->right->parent = p->parent;
delete(p);
}else if (p->left != nullptr&&p->right == nullptr)
else if (p->parent->left!=nullptr && p->parent->left->data == p->data)
p->parent->left = p->left, p->left->parent = p->parent;
else if (p->parent->right!=nullptr && p->parent->right->data == p->data)
p->parent->right = p->left, p->left->parent = p->parent;
delete(p);
}else
p->data = it->data;
if (tmp != p)
else
if (it->left != nullptr)
it->left->parent = tmp;
delete(it);
}} iterator lower_bound_aux(node_ptr p, const value_type& x)
else
return lower_bound_aux(p->right, x);
} iterator upper_bound_aux(node_ptr p, const value_type& x)
else
return upper_bound_aux(p->right, x);
} void erase_val_aux(node_ptr p,const value_type& key)
public:
bstree() :node(nullptr),data_cnt(0) {}
bool empty()
size_type size()
iterator begin()
iterator it(node);
while (it.p.node->left != nullptr)
it.p.node = it.p.node->left;
return it;
} iterator end()
iterator find_max()
node_ptr root()
pairinsert(const value_type& val)
iterator find(const value_type& key)
iterator lower_bound(const value_type& x)
iterator upper_bound(const value_type& x)
void erase(iterator pos)
void erase(const value_type& x)
void clear()
};
從零開始寫STL 容器 vector
vector又稱為動態陣列,那麼動態體現在 vector和一般的陣列又有什麼區別?vector中各個函式的實現原理是怎樣的,我們怎樣使用會更高效?在容器類的最前面我們會看到許多的typedef 常見的如下 public typedef t value type typedef value type ...
二叉搜尋樹開始部分 驗證二叉搜尋樹 附帶介紹
每個節點中的值必須大於儲存在其左側子樹中的任何值。每個節點中的值必須小於儲存在其右子樹中的任何值。首先二叉搜尋樹有個特性即它的中序遍歷為乙個遞增的有序序列那麼我們就可以利用這個特性來驗證二叉搜尋樹,我們只要判斷list.get i 1 list.get i 就可以判斷不是二叉搜尋樹,如果迴圈完畢則是...
二叉搜尋樹 二叉搜尋樹
題目 二叉搜尋樹 time limit 2000 1000 ms j a others memory limit 32768 32768 k j a others total submission s 6945 accepted submission s 3077 problem descripti...