BST(binary search tree)是具有下列性质的二叉树:
1.若左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
2.若右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
3.左、右子树也分别为二叉排序树;
4.没有键值相等的节点。
BST的一些基本操作(添加结点,查找,删除,遍历)
添加:
添加元素elem从根结点开始比较,如果elem比根结点小,与根结点的左子树比较,如果elem比根节点大,与根结点的右子树比较;再以此子树作为根结点。
如此递归下去...
如果找到某结点的左/右子树结点为NULL,则添加到这个结点的左/右子树结点上。
添加新元素后的BST完全满足上述(BST)性质。
查找:
查找元素elem从根结点开始比较,如果elem比根结点小,与根结点的左子树比较,如果elem比根结点大,与根结点的右子树比较;再以此子树作为根结点。
如此递归下去...
相等则查找到。
删除(分3种情况):
1.删除元素elem没有子树,直接删除
2.删除元素elem有一个子树,则elem的父结点指向elem的子树(elem元素被它的子树取代),删除elem结点
3.删除元素elem左右子树完整,有2种方法:
1)取元素elem结点的右子树中的最小值来取代elem,然后删除elem。
2)取元素elem结点的左子树中的最大值来取代elem,然后删除elem。
这样做不会破坏BST的属性。
遍历:
DLR(前序遍历),LDR(中序遍历),LRD(后序遍历) ,是以根结点的位置来决定名称的(D在L与R中间就是中序遍历)。对于BST,中序遍历的结果就是排序(升序)之后的结果。
Level Order Traverse(层序遍历),就是从树的最上层依次想最下层遍历,遍历的过程就是“广度优先搜索”的过程。
BST的属性与操作还是很简单的,只要在纸上多画画就会比较清楚;难点是用递归的方式来表达出来,一不小心就忘记自己丢到哪一层去了...*&#%&$^&*...
1.若左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
2.若右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
3.左、右子树也分别为二叉排序树;
4.没有键值相等的节点。
BST的一些基本操作(添加结点,查找,删除,遍历)
添加:
添加元素elem从根结点开始比较,如果elem比根结点小,与根结点的左子树比较,如果elem比根节点大,与根结点的右子树比较;再以此子树作为根结点。
如此递归下去...
如果找到某结点的左/右子树结点为NULL,则添加到这个结点的左/右子树结点上。
添加新元素后的BST完全满足上述(BST)性质。
查找:
查找元素elem从根结点开始比较,如果elem比根结点小,与根结点的左子树比较,如果elem比根结点大,与根结点的右子树比较;再以此子树作为根结点。
如此递归下去...
相等则查找到。
删除(分3种情况):
1.删除元素elem没有子树,直接删除
2.删除元素elem有一个子树,则elem的父结点指向elem的子树(elem元素被它的子树取代),删除elem结点
3.删除元素elem左右子树完整,有2种方法:
1)取元素elem结点的右子树中的最小值来取代elem,然后删除elem。
2)取元素elem结点的左子树中的最大值来取代elem,然后删除elem。
这样做不会破坏BST的属性。
遍历:
DLR(前序遍历),LDR(中序遍历),LRD(后序遍历) ,是以根结点的位置来决定名称的(D在L与R中间就是中序遍历)。对于BST,中序遍历的结果就是排序(升序)之后的结果。
Level Order Traverse(层序遍历),就是从树的最上层依次想最下层遍历,遍历的过程就是“广度优先搜索”的过程。
BST的属性与操作还是很简单的,只要在纸上多画画就会比较清楚;难点是用递归的方式来表达出来,一不小心就忘记自己丢到哪一层去了...*&#%&$^&*...
详情见代码吧:
#include <iostream>
#include <deque>
using namespace std;
class binarySearchsTree
{
public:
binarySearchsTree()
{
//初始化根结点
root = NULL;
}
struct bstNode
{
int data;
bstNode *left;
bstNode *right;
};
//添加结点
//添加结点elem从根结点开始比较,如果elem比根结点小,与根结点左子树比较,如果elem比根结点大,与根结点右子树比较;
//如此递归下去,直到找到某结点的左/右子树结点为NULL,添加到这个结点的左/右子树结点上。
int add(int elem)
{
bstNode *pNode = new bstNode;
pNode->left = NULL;
pNode->right = NULL;
pNode->data = elem;
if(NULL == root)
{
root = pNode;
return 1;
}
bstNode *pCurrent = root;
bstNode *pPreNode;
//这里也可以用递归
while(NULL != pCurrent)
{
//pPreNode临时指针,用于定位到某结点(添加结点elem的父结点);pCurrent在移动过程中最后指向NULL(pPreNode->left/right == pCurrent == NULL).
pPreNode = pCurrent;
if( elem < pCurrent->data)
pCurrent = pCurrent->left;
else
pCurrent = pCurrent->right;
}
if( pPreNode->data > elem)
pPreNode->left = pNode;
else
pPreNode->right = pNode;
return 1;
}
//find
bstNode *find(bstNode* f_root, int elem)
{
bstNode *f_node;
if(NULL == f_root)
{
return NULL;
}
//递归退出条件
if(elem == (f_root->data))
{
return f_root;
}
if(elem < f_root->data)
return find(f_root->left, elem);
else
return find(f_root->right, elem);
}
int find(int elem)
{
bstNode *f_node = find(root, elem);
cout<<f_node->data<<endl;
return 1;
}
//delete
struct bstNode * deleteElem(struct bstNode *del_root, int elem)
{
if(del_root == NULL)
return del_root;
//定位删除结点elem的位置
else if(elem < del_root->data)
del_root->left = deleteElem(del_root->left, elem);
else if(elem > del_root->data)
del_root->right = deleteElem(del_root->right, elem);
else
{
//如果删除结点elem没有子树,直接删除
if(del_root->left == NULL && del_root->right == NULL)
{
delete del_root;
del_root = NULL;
}
//如果删除结点elem左子树为NULL(只有右子树),则原elem指针指向下一(右子树)结点,删除原elem元素
else if(del_root->left == NULL)
{
struct bstNode *tmp = del_root;
//删除结点elem被它的右子树取代
del_root = del_root->right;
delete tmp;
}
//如果删除结点elem右子树为NULL(只有左子树),则原elem指针指向下一(左子树)结点,删除原elem元素
else if(del_root->right == NULL)
{
struct bstNode *tmp = del_root;
del_root = del_root->left;
delete tmp;
}
//删除结点elem有左、右子树
else
{
//查找右子树的最小值
struct bstNode *tmp = findMin(del_root->right);
//struct bstNode *tmp = findMax(del_root->left);
del_root->data = tmp->data;
//这里“很巧妙”,递归查找该删除的元素tmp->data,此时的tmp->data是没有子树的结点,将会被直接删除
del_root->right = deleteElem(del_root->right, tmp->data);
}
}
return del_root;
}
//找最小值,最小值一定在左子树,且它的左子树为空
bstNode* findMin(bstNode* root)
{
static bstNode* pre_node;
if(root == NULL)
{
return pre_node;
}
else
{
pre_node = root;
return findMin(root->left);
}
}
void deleteElem(int elem)
{
deleteElem(root,elem);
cout<<endl;
}
//traverse
int LDR_traverse(bstNode* ldr_root)
{
if(NULL != ldr_root)
{
LDR_traverse(ldr_root->left);
cout<<ldr_root->data<<" ";
LDR_traverse(ldr_root->right);
}
return 1;
}
void LDR_traverse()
{
LDR_traverse(root);
cout<<endl;
}
//层序遍历二叉树,即广度优先。
//从根结点开始遍历,存入队列;出队列,遍历此结点左子树,有值,存入队列,再遍历此结点右子树,有值,存入队列;
//递归:出队列,遍历此结点左子树,有值,存入队列,再遍历此结点右子树,有值,存入队列;
int level_traverse()
{
if(root == NULL)
{
return 0;
}
deque<bstNode *> dequesTree;
dequesTree.push_back(root);
while(dequesTree.size())
{
bstNode *p = dequesTree.front();
dequesTree.pop_front();
cout << (p->data)<<" ";
if(p->left)
{
dequesTree.push_back(p->left);
}
if(p->right)
{
dequesTree.push_back(p->right);
}
}
cout<<endl;
}
private:
bstNode *root;
};
int main()
{
binarySearchsTree oBST;
int data[11] = {7,3,9,10,1,4,15,5,19,8,11};
for(int i=0; i<11; i++)
{
//init
oBST.add(data[i]);
}
oBST.LDR_traverse();
//find
oBST.find(8);
//add
oBST.add(16);
oBST.LDR_traverse();
oBST.level_traverse();
//delete
oBST.deleteElem(7);
oBST.LDR_traverse();
oBST.level_traverse();
return 1;
}