一、二叉搜尋樹的概念
又稱二叉排序樹,它或者是一棵空樹,或者是具有以下性質的二叉樹
1、若它的左子樹不為空,則左子樹上所有節點的值都小於根節點的值
2、若它的右子樹不為空,則右子樹上所有節點的值都大於根節點的值
3、它的左右子樹也分別為二叉搜尋樹
二、對二叉搜尋樹的操作
1、搜尋
規則:從根節點開始,
若根節點不為空
如果根節點key等於查詢節點key 返回true
如果根節點key大於查詢節點key 在其左子樹查詢
如果根節點key小於查詢節點key 在其右子樹查詢
否則,返回false
遞迴**:
bool _searchp(pnode proot, k key)//查詢遞迴
else
return false;
}
非遞迴**:
bool _search(pnode proot, k key)//查詢非遞迴
return false;
}
2、插入
在向二叉搜尋樹中插入新元素時,必須先檢測這個元素是否在樹中已經存在。如果搜尋成功,說明該元素已經存在,
則不進行插入;
否則將新元素加入到搜尋停止的地方
規則:如果是空樹,直接插入,然後返回true
搜尋需要插入的位置 --比較當前節點與要插入節點的key值大小
-- 如果要插入節點的key值小於當前節點key值,則與當前節點的左子樹的key值比較
--如果要插入節點的key值大於當前節點key值,則與當前節點的右子樹的key值比較
--如果要插入節點的key值等於當前節點key值,返回false
--如此迴圈,直至當前節點為空
插入新節點
遞迴**:
bool _insertp(pnode &proot,pnode pre, k key, v value)//插入遞迴
if (!search(key))
else
}return false;
}
非遞迴**:
bool _insert(pnode &proot,pnode pre, k key, v value)//插入非遞迴
while (pcur)
pnode parent = pre;
if (parent->_key > key)
parent->_left = temp;
else
parent->_right = temp;
temp->_parent = parent;
return true;
}
3、刪除
首先查詢元素是否在二叉搜尋樹中,如果不存在,則返回;否則要刪除的結點可能分下面四種
情況:1、要刪除的結點無孩子結點;
2、要刪除的結點只有左孩子結點;
3、要刪除的結點只有右孩子結點;
4、要刪除的結點有左、右孩子結點;
情況1可以歸類到2或者3
對於上述情況,相應的刪除方法如下:
a、直接刪除該結點
b、刪除該結點且使被刪除節點的雙親結點指向被刪除節點的左孩子結點;
c、刪除該結點且使被刪除節點的雙親結點指向被刪除結點的右孩子結點;
d、在它的右子樹中尋找中序下的第乙個結點(key值最小),用它的值填補到被刪除節點中,再來處理該結點的刪除問題
**如下:
bool _delete(pnode &proot, k key)//刪除非遞迴
if (pcur->_left == null && pcur->_right != null)//要刪除節點只有右孩子節點
else if (pcur->_right != null && pcur->_left != null)//要刪除節點有左、右孩子節點
else if (pcurr->_left == null && pcurr->_right != null)//要刪除節點只有右孩子
else
pcurr = pcurr->_left;
}} else
return false;
}
三、二叉搜尋樹效能分析
插入和刪除操作的主體部分是查詢,查詢效率代表了二叉排序中上各個操作的效能。對有n個結點的
二叉排序樹,若每個元素查詢的概率相等,則二叉搜尋樹平均查詢長度是結點在二叉搜尋樹的深度的函式
即結點越深,則比較次數越多
最壞情況下,二叉排序樹的平均查詢長度為o(n),一般情況下平均查詢長度為o(lbn)
全部**:
#includeusing namespace std;
templatestruct searchbintreenode
struct searchbintreenode* _parent;
struct searchbintreenode* _left;
struct searchbintreenode* _right;
k _key;
v _value;
};//迭代器
templatestruct bstiterator
bstiterator(pnode phead, pnode pnode)
: _pnode(pnode)
, _phead(phead)
{} bstiterator(self& s)
: _pnode(s._pnode)
{} self &operator++()
self operator++(int)
self &operator--()
self operator--(int)
bool operator==(const self& s)
bool operator!=(const self& s)
k operator*()
pnode operator->()
void increase()
else
if (_pnode->_right != parent)
_pnode = parent;
} }void decrease()
else
_pnode = parent;
} }private:
pnode _pnode;
pnode _phead;
};templateclass searchbintree
searchbintree(const k* arr,size_t size) }
bool search(k key)//搜尋
bool delete(k key)//刪除
void inorder()
private:
bool _insertp(pnode &proot,pnode pre, k key, v value)//插入遞迴
if (!search(key))
else
}return false;
} bool _insert(pnode &proot,pnode pre, k key, v value)//插入非遞迴
while (pcur)
pnode parent = pre;
if (parent->_key > key)
parent->_left = temp;
else
parent->_right = temp;
temp->_parent = parent;
return true;
} bool _searchp(pnode proot, k key)//查詢遞迴
else
return false;
} bool _search(pnode proot, k key)//查詢非遞迴
return false;
} bool _delete(pnode &proot, k key)//刪除非遞迴
if (pcur->_left == null && pcur->_right != null)//要刪除節點只有右孩子節點
else if (pcur->_right != null && pcur->_left != null)//要刪除節點有左、右孩子節點
else if (pcurr->_left == null && pcurr->_right != null)//要刪除節點只有右孩子
else
pcurr = pcurr->_left;
}} else
return false;
} void _inorder(pnode proot)//中序遍歷 }
pnode _proot;
};int main()
; searchbintreetree(arr, 10);
tree.inorder();
cout << endl;
tree.delete(0);
tree.inorder();
return 0;
}
執行結果:
二叉搜尋樹 二叉搜尋樹
題目 二叉搜尋樹 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...
二叉搜尋樹 修剪二叉搜尋樹
第一反應是重構,看來別人的解答發現,其實不用重構那麼複雜。treenode trimbst treenode root,int low,int high if root val high 下一層處理完左子樹的結果賦給root left,處理完右子樹的結果賦給root right。root left ...
樹 二叉樹 二叉搜尋樹
給定乙個二叉樹,判斷其是否是乙個有效的二叉搜尋樹。假設乙個二叉搜尋樹具有如下特徵 節點的左子樹只包含小於當前節點的數。節點的右子樹只包含大於當前節點的數。所有左子樹和右子樹自身必須也是二叉搜尋樹。示例 1 輸入 2 13輸出 true 示例 2 輸入 5 14 3 6輸出 false 解釋 輸入為 ...