版权声明:转载请写明出处,谢谢! https://blog.csdn.net/wilson1068/article/details/88429190
二叉查找树 BST
二叉查找树:二叉查找树(Binary Search Tree)又称二叉搜索树、二叉排序树(Binary Sort Tree)或有序二叉树(ordered binary tree)。
具有以下特性:
- 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
- 左、右子树也分别为二叉排序树;
- 没有键值相等的节点。
性质:对二叉查找树进行中序遍历,可以得到有序的数列。
二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低。
二叉查找树时间复杂度
算法 | 平均 | 最差 | 说明 |
---|---|---|---|
空间 | |||
搜索 | 数列有序,树退化成线性表时。效率最低。 | ||
插入 | 数列有序,树退化成线性表时。效率最低。 | ||
删除 | 数列有序,树退化成线性表时。效率最低。 |
二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、多重集、关联数组等。
虽然二叉查找树的最坏效率是 ,但它支持动态查询,且有很多改进版的二叉查找树可以使树高为 ,从而将最坏效率降至 ,如 AVL 树、红黑树等。
二叉查找树建立,插入,删除,查找
基本符合二分查找的规则。
比较复杂的就是删除操作。
如果删除的节点有左右子树,那么需要保证删除后的左右子树依然满足:左子树所有节点的值 < 新节点,新节点 < 右子树所有节点的值。
那么,删除这种节点时,需要选择左子树最大的值,或者右子树最小的值。
那么其实只要找到左子树最大的值,或者右子树最小的值替换到当前节点的值即可。
void createBinarySearchTree(stBinaryTreeNode * root, void ** datas, const int datas_len) {
for (int i = 0; i < datas_len; ++ i) {
insertBinarySearchTree(root, datas[i]);
}
}
int insertBinarySearchTree(stBinaryTreeNode * root, void * data) {
stBinaryTreeNode * node = (stBinaryTreeNode *) malloc(sizeof(stBinaryTreeNode));
node->data = data;
node->lchild = node->rchild = NULL;
if (root == NULL) {
root = node;
return 1;
}
stBinaryTreeNode * head = root;
// 类似于二分查找
for ( ; ; ) {
if ((int)data < (int)head->data) { // 查找左子树
if (head->lchild) {
head = head->lchild;
} else {
head->lchild = node;
break;
}
} else if ((int)data > (int)head->data) { // 查找右子树
if (head->rchild) {
head = head->rchild;
} else {
head->rchild = node;
break;
}
} else {
return 0;
}
}
return 1;
}
int removeBinarySearchTree(stBinaryTreeNode ** proot, void * data) {
stBinaryTreeNode * node = *proot;
stBinaryTreeNode * parent_node = root;
int find = 0;
while (node != NULL) {
if ((int)data < (int)node->data) { // 查找左子树
parent_node = node;
node = node->lchild;
} else if ((int)data > (int)node->data) { // 查找右子树
parent_node = node;
node = node->rchild;
} else /* if ((int)data == (int)node->data) */ {
break;
}
}
if (node == NULL) { // 未找到
return 0;
}
#define NODE_IS_ROOT 0x10000
#define NODE_IS_L_NULL 0x01000
#define NODE_IS_R_NULL 0x00100
#define NODE_IN_L_PNODE 0x00010
#define NODE_IN_R_PNODE 0x00001
int node_pnode_status = 0;
if (node == *proot) node_pnode_status |= NODE_IS_ROOT;
if (node->lchild == NULL) node_pnode_status |= NODE_IS_L_NULL;
if (node->rchild == NULL) node_pnode_status |= NODE_IS_R_NULL;
if (parent_node->lchild == node) node_pnode_status |= NODE_IN_L_PNODE;
if (parent_node->rchild == node) node_pnode_status |= NODE_IN_R_PNODE;
switch(node_pnode_status) {
case (NODE_IS_ROOT | NODE_IS_L_NULL | NODE_IS_R_NULL | 0): // 叶子节点(node是根节点)
*proot = NULL;
break;
case (0 | NODE_IS_L_NULL | NODE_IS_R_NULL | NODE_IN_L_PNODE | 0): // 叶子节点(node是左节点)
parent_node->lchild = NULL;
break;
case (0 | NODE_IS_L_NULL | NODE_IS_R_NULL | 0 | NODE_IN_R_PNODE): // 叶子节点(node是右节点)
parent_node->rchild = NULL;
break;
case (NODE_IS_ROOT | 0 | NODE_IS_R_NULL | 0 | 0): // 左单只子树(node是根节点)
*proot = node->rchild;
break;
case (NODE_IS_ROOT | NODE_IS_L_NULL | 0 | 0 | 0): // 右单只子树(node是根节点)
*proot = node->rchild;
break;
case (NODE_IS_ROOT | 0 | NODE_IS_R_NULL | NODE_IN_L_PNODE | 0): // 左单只子树(node是左节点)
parent_node->lchild = node->lchild;
break;
case (NODE_IS_ROOT | NODE_IS_L_NULL | 0 | NODE_IN_L_PNODE | 0): // 右单只子树(node是左节点)
parent_node->rchild = node->lchild;
break;
case (NODE_IS_ROOT | 0 | NODE_IS_R_NULL | 0 | NODE_IN_R_PNODE): // 右单只子树(node是左节点)
parent_node->lchild = node->rchild;
break;
case (NODE_IS_ROOT | NODE_IS_L_NULL | 0 | 0 | NODE_IN_R_PNODE): // 右单只子树(node是右节点)
parent_node->rchild = node->rchild;
break;
case (NODE_IS_ROOT | 0 | 0 | 0 | 0): // 左右子树非空(node是根节点)
case (NODE_IS_ROOT | 0 | 0 | NODE_IN_L_PNODE | 0): // 左右子树非空(node是左节点)
case (NODE_IS_ROOT | 0 | 0 | 0 | NODE_IN_R_PNODE): // 左右子树非空(node是左节点)
{
stBinaryTreeNode * tmp = node;
stBinaryTreeNode * s = node->lchild;
while (s->rchild) {
tmp = s;
s = s->rchild;
}
node->data = s->data;
if (tmp == node) {
node->lchild = s->lchild;
} else {
node->rchild = s->lchild;
}
node = s;
}
break;
}
free(node);
return 1;
}
stBinaryTreeNode * searchBinarySearchTree(stBinaryTreeNode * root, void * data) {
stBinaryTreeNode * node = root;
while (node) {
if ((int)data < (int)node->data) {
node = node->lchild;
} else if ((int)data > (int)node->data) {
node = node->rchild;
} else {
return node;
}
}
return NULL;
}