二分搜索树
1 添加元素
添加元素的思路:
1)判断,若树为空,则创建一个新的节点,直接使用添加的元素初始化;
2)不为空,则比较添加元素与节点元素的大小,然后使用递归左(右)子树;
3)递归终止条件:节点为空,创建新的节点并初始化返回。
//向以node为根的二分搜索数中插入元素e,递归算法
//返回插入新节点后二分搜索树的根
TNode<T> *add(TNode<T> *node,T e) {
if(node== nullptr) {
size++;
return new TNode<T>(e);
}
if(node->e>e){
node->left=add(node->left,e);//递归
}else if(node->e<e){
node->right=add(node->right,e);
}
return node;
}
2 前序遍历
前序遍历、中序遍历、后序遍历的概念就不在这里讲了,三者的区分就是注意根节点何时遍历。比如前序遍历,就是先遍历根节点,再遍历左右子节点。
这里注意使用递归调用,递归调用的终止条件:节点为空。
递归写法:
//前序遍历以node为根的二分搜索树,递归算法
void preOrder(TNode<T> *node){
if(node==nullptr)
return ;
std::cout<<node->e;
preOrder(node->left);
preOrder(node->right);
}
非递归写法: 使用栈
1)先将根节点压入栈中,然后取出访问;
2)将左节点、右节点依次压入栈中,然后再将左节点作为根节点;
3)当栈为空时,访问结束。
e(e);
size++;
void preOrderNR(){
std::stack<Node<T> *> stack;
stack.push(root);
while (!stack.empty()) {
TNode<T> *cur = stack.top();
std::cout << cur->e << " ";
stack.pop();
if (cur->right != nullptr)
stack.push(cur->right);
if (cur->left != nullptr)
stack.push(cur->left);
}
std::cout<<std::endl;
}
3 层序遍历
层序遍历又称为广度优先遍历。层序遍历通常使用非递归方式实现,需要借助队列实现。每次将待遍历的元素存入队列中,再将它的左右子节点排入队列。
//层序遍历
void levelOrder(){
std::queue<TNode<T> *> *q=new std::queue<TNode<T> *>();
q->push(root);
while (!q->empty()){//队列不为空
TNode<T> *cur=q->front();
q->pop();
std::cout<<cur->e<<" ";
if(cur->left!= nullptr){
q->push(cur->left);//左子节点排入队列中
}
if(cur->right!= nullptr){
q->push(cur->right);//右子节点排入队列中
}
std::cout<<std::endl;
}
}
4 删除元素
1)删除最大元素和最小元素
最小元素,只需要不断遍历树的左子节点,走到底就是最小元素。最大元素就是向右走。
TNode<T> *removeMin(TNode<T> *node){
if(node->left==nullptr){//向左走,寻找最小元素
//保存最小元素节点的右子节点
TNode<T> *rightNode=node->right;
delete node;//删除最小元素节点
size--;
return rightNode;//返回保存的节点
}
node->left=removeMin(node->left);
return node;
}
2)删除仍意元素(Hibbard Deletion)
分别判断节点的情况:
第一,删除只有左孩子的节点;
第二,删除只有右孩子的节点;
第三,删除左右都有孩子的节点。(选择该节点的右子树中最小的值代替该节点)
TNode<T> *remove(TNode<T> *node,T e){
if(node==nullptr)
return nullptr;
if(node->e>e){
node->left=remove(node->left,e);
return node;
}else if(node->e<e){
node->right=remove(node->right,e);
return node;
}
else{
if(node->left== nullptr){//左子树为空
TNode<T> *rightNode=node->right;
delete node;
size--;
return rightNode;
}
if(node->right== nullptr){//右子树为空
TNode<T> *leftNode=node->left;
delete node;
size--;
return leftNode;
}
TNode<T> *successor=min(node->right);//获取该节点右子树的最小值
successor->right=removeMin(node->right);
successor->left=node->left;
node->left=node->right= nullptr;
return successor;
}
}