基本概念
-
BST
二叉查找树又称二叉搜索树或者二叉排序树;它可以是一个空树或者是一个二叉树,既有链表的快速插入与删除的特点,又有数组快速查找的优势。
-
基本性质
二叉查找树非空时,具有以下性质:
①.若左子树非空,则左子树所有节点均小于根节点的值
②.若右子树非空,则右子树所有节点均大于跟节点的值
③.左右子树也是二叉查找树
④.没有键值相等的节点
-
基本操作
①.插入:插入一个新值
②.查找:根据键值查找节点
③.删除:根据键值删除节点
-
其他
①.前驱节点:所有节点从小到大到大排列后的小于本节点键值的前一个节点
②.后继节点:所有节点从小到大到大排列后的大于本节点键值的后一个节点
③.中序遍历:按照“左节点”、“本节点”、“右节点”的顺序遍历树;中序遍历的结果就是元素值从小到大的排列
④.前序遍历:按照“本节点”、“左节点”、“右节点”的顺序遍历树
⑤.后序遍历:按照“左节点”、“右节点”、“中节点”的顺序遍历树
实现方法
// BST节点类
class TBSTNode
{
private:
TBSTNode * leftChild;//左子树
TBSTNode * rightChild;//右子树
int val; //节点值
TBSTNode * parentNode;//父节点
public:
//构造函数
TBSTNode(int key) :leftChild(nullptr), rightChild(nullptr), val(key),parentNode(nullptr) {};
TBSTNode(int key, TBSTNode * node) :leftChild(nullptr), rightChild(nullptr), val(key), parentNode(node) {};
//析构函数,释放子节点
~TBSTNode()
{
if( leftChild )
{
delete leftChild;
leftChild = nullptr;
}
if( rightChild )
{
delete rightChild;
rightChild = nullptr;
}
};
// 公开接口
int getKey()//访问节点值
{
return val;
};
void setKey(int key)//重置节点值
{
val = key;
};
TBSTNode * getLeft()//访问左子树
{
return leftChild;
};
void setLeft(TBSTNode * node)//重置左子树
{
leftChild = node;
};
TBSTNode * getRight()//访问右子树
{
return rightChild;
};
void setRight(TBSTNode * node)//重置右子树
{
rightChild = node;
};
TBSTNode * getParent()//访问父节点
{
return parentNode;
};
void setParent(TBSTNode * node)//重置父节点
{
parentNode = node;
};
};
// BST 树类
class TBSTree
{
public:
TBSTree() :root(nullptr) {};
~TBSTree()
{
if (root)
{
delete root;
root = nullptr;
}
};
//对外接口
void insertKey(int key)//插入一个值
{
if (!root)
{
root = new TBSTNode(key);
}
else
{
insertKey(root, key);
}
}
TBSTNode * searchKey(int key)// 根据值查询节点
{
TBSTNode * temp = root;//遍历树
while (temp)
{
if (key > temp->getKey())// 比本节点大,继续比较右节点
{
temp = temp->getRight();
}
else if (key < temp->getKey()) // 比本节点大,继续比较左节点
{
temp = temp->getLeft();
}
else
return temp;
}
return nullptr;
};
TBSTNode * getNext(TBSTNode * node)//查询一个节点的后继节点
{
if (node)
{
vector<TBSTNode *> tempvector;
toVectorByMidorder(node->getRight(), tempvector);
if (tempvector.size() > 0)
{
TBSTNode * nextNode = tempvector[0];//后继节点
return nextNode;
}
}
return nullptr;
};
TBSTNode * getPre(TBSTNode * node)//查询一个节点的前驱节点
{
if (node)
{
vector<TBSTNode *> tempvector;
toVectorByMidorder(node->getLeft(), tempvector);
if (tempvector.size() > 0)
{
TBSTNode * preNode = tempvector[tempvector.size()-1];//前驱节点
return preNode;
}
}
return nullptr;
}
void deleteKey(int key)//按值删除节点
{
TBSTNode * temp = searchKey(key);
if (temp)
{
deleteKey(temp);
}
}
void printByMid()//中序打印数
{
printByMid(root);
};
private:
TBSTNode * root;
void insertKey(TBSTNode * root, int key)// 在某子树插入新值
{
TBSTNode * parent = nullptr;//定位插入点
TBSTNode * temp = root;//用于遍历树
while (temp)
{
parent = temp;
if (key > temp->getKey())// 比本节点大,继续比较右节点
{
temp = temp->getRight();
}
else if (key < temp->getKey()) // 比本节点大,继续比较左节点
{
temp = temp->getLeft();
}
else
return;
}
if ( key > parent->getKey())
{
parent->setRight(new TBSTNode(key,parent));//做为右子节点
}
else if (key < parent->getKey())
{
parent->setLeft(new TBSTNode(key,parent));//做为左子节点
}
}
void printByMid(TBSTNode * root )
{
if (root)
{
printByMid(root->getLeft());
cout << root->getKey() << " ";
printByMid(root->getRight());
};
};
void toVectorByMidorder(TBSTNode * root,vector<TBSTNode * > &temp_vector)
{
if (root)
{
toVectorByMidorder(root->getLeft(), temp_vector);
temp_vector.push_back(root);
toVectorByMidorder(root->getRight(), temp_vector);
}
}
void deleteKey(TBSTNode * node)
{
TBSTNode * temp = node;
if (temp)
{
TBSTNode * tempParent = temp->getParent();//目标父节点
TBSTNode * left = temp->getLeft();//目标左子树
TBSTNode * right = temp->getRight();//目标右子树
if (left == nullptr)
{
if (right == nullptr)//没有左右子节点,直接删除
{
if (tempParent == nullptr){}//父节点为空
else
{
//断开和父节点的关联
if (tempParent->getLeft() == temp)
{
tempParent->setLeft(nullptr);
}
else
{
tempParent->setRight(nullptr);
}
}
delete temp;//释放本节点内存
temp = nullptr;
}
else //只有右节点,右子树继承父节点
{
//右节点关联到父节点,取代本节点位置
right->setParent(tempParent);
if ( tempParent )
{
if (tempParent->getLeft() == temp)
{
tempParent->setLeft(right);
}
else
{
tempParent->setRight(right);
}
}
temp->setRight(nullptr);//本节点和其子节点断开
delete temp;
temp = nullptr;
}
}
else
{
if (right == nullptr)//只有左节点,左子树继承父节点
{
//右节点关联到父节点,取代本节点位置
left->setParent(tempParent);
if (tempParent)
{
if (tempParent->getLeft() == temp)
{
tempParent->setLeft(left);
}
else
{
tempParent->setRight(left);
}
}
temp->setLeft(nullptr);
delete temp;
temp = left;
}
else//用后继节点取代本节点
{
TBSTNode * nextNode = getNext(temp);
temp->setKey(nextNode->getKey());//更新为后继节点的值
deleteKey(nextNode);// 删除后继节点
}
}
}
}
};