介绍
二分查找树是一种能够快速维护排序数值集的数据结构。
- 二叉树:因为每个节点最好有两个子节点
- 查找树:可以以O(log(n))的时间来查询值是否存在
二分查找树与普通二叉树的区别:
- 左子树的所有节点小于根节点
- 右子树的所有节点大于根节点
- 每个节点的所有子树也是二分查找树,满足上面两个条件
上图中,右边的二叉树并不是二分查找树,因为节点3的右子树包含小于节点3的值。
二分查找树可以进行两个基本操作
检查一个值是否在二分查找树
如果一个值小于根节点,那么值不会在右子树,需要在左子树上查找。如果一个值大于根节点,那么值不会在左子树,需要在右子树上查找。
If root == NULL
return NULL;
If number == root->data
return root->data;
If number < root->data
return search(root->left)
If number > root->data
return search(root->right)
如果值发现,我们返回这个值,以至在每个递归步骤中进行传递。如下图所示
如果值没有发现,那么最终达到一个叶子节点的左节点(NULL)或者右节点(NULL),然后在每个递归步骤进行传递。
在二分查找树中添加值
添加值到正确的位置上类似于查询,因为我们需要维护左子树小于根节点,右子树大于根节点。
依赖于值的大小,我们进入根节点的左子树或者右子树,当我们达到左节点或者右节点为NULL时,在这个位置添加一个新节点,表示这个值。
If node == NULL
return createNode(data)
if (data < node->data)
node->left = insert(node->left, data);
else if (data > node->data)
node->right = insert(node->right, data);
return node;
我们添加新节点,然而并不会改变二分查找树的其他部分。上面的代码是return node,如果是NULL,那么新创建的节点返回,添加到它的父节点上,除此之外,相同的节点被返回,并不会进行任何改变,直到返回到根节点。
实现方法:
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node* left;
struct node* right;
};
struct node* createNode(value){
struct node* newNode = malloc(sizeof(struct node));
newNode->data = value;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
struct node* insert(struct node* root, int data)
{
if (root == NULL) return createNode(data);
if (data < root->data)
root->left = insert(root->left, data);
else if (data > root->data)
root->right = insert(root->right, data);
return root;
}
void inorder(struct node* root){
if(root == NULL) return;
inorder(root->left);
printf("%d ->", root->data);
inorder(root->right);
}
int main(){
struct node *root = NULL;
root = insert(root, 8);
insert(root, 3);
insert(root, 1);
insert(root, 6);
insert(root, 7);
insert(root, 10);
insert(root, 14);
insert(root, 4);
inorder(root);
}
输出为:
1 ->3 ->4 ->6 ->7 ->8 ->10 ->14 ->