小学生必知必会——(BSTREE)二叉搜索树
二叉排序树(Binary Sort Tree,简称 BST )又叫二叉查找树和二叉搜索树。最少能以O(logn)查找删除元素。
性质:
二叉搜索树的本质是一颗二叉树,根节点的左孩子小于根节点,右孩子大于根节点,并且中序遍历是有序的。
插入节点
insert_Node 插入一个key如果树为空(NULL)key申请的节点为根节点。如果key小于根节点(root)的值key插入到左孩子节点,如果key大于根节点(root)的值key插入右孩子节点,否则遇到了重复节点直接返回。
前置节点
找到根节点的左孩子,在一直向右遍历到叶子节点就是根节点的前置节点。(根节点不是只有一个,对当前节点进行操作就可以暂时把当前节点当成根节点)
删除节点
情况(1) 度为0或1的节点
如果度为1,删除该节点,返回唯一孩子节点代替父节点
度为0直接删除,返回NULL
情况(2)度为2的节点
找到前置节点,将前置节点的值覆盖掉当前节点的值,删除前置节点退化到了情况(1)。
遍历二叉树
中序遍历
当前节点为空(NULL)空操作原路返回。
如果左子树不为NULL 中序遍历左子树
访问根节点
如果右子树不为NULL 中序遍历右子树
前序遍历
当前节点为空(NULL)空操作原路返回。
访问跟节点
如果左子树不为NULL 前序遍历左子树
如果右子树不为NULL 前序遍历右子树
释放二叉树
同上 将printf改成free释放节点
/*************************************************************************
> File Name: BS_Tree.c
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int key;
struct Node *lchild, *rchild;
}Node;
Node *getNewNode(int key)
{
Node *p = (Node *)malloc(sizeof(Node));
p->key = key;
p->lchild = p->rchild = NULL;
return p;
}
void inorder(Node *root);
void Preorder(Node *root);
Node *insert_Node(Node *root, int key)
{
if(root == NULL) return getNewNode(key);
if(root->key == key) return root;
if(root->key > key)
{
root->lchild = insert_Node(root->lchild, key);
}
else
{
root->rchild = insert_Node(root->rchild, key);
}
return root;
}
Node *predecessor(Node *root)
{
Node *temp = root->lchild;
while(temp != NULL) temp = temp->rchild;
return temp;
}
Node *earse_Node(Node *root, int key)
{
if(root == NULL) return NULL;
if(root->key > key)
{
root->lchild = earse_Node(root->lchild, key);
}
else if(root->key < key)
{
root->rchild = earse_Node(root->rchild, key);
}
else
{
if(root->lchild == NULL || root->rchild == NULL)
{
Node *temp = root->lchild != NULL ? root->lchild : root->rchild;
free(root);
return temp;
}
else
{
Node *temp = predecessor(root);
root->key = temp->key;
root->lchild = earse_Node(root->lchild, temp->key);
}
}
return root;
}
void clear(Node *root)
{
if(root == NULL) return ;
if(root->lchild != NULL) clear(root->lchild);
if(root->rchild != NULL) clear(root->rchild);
free(root);
return ;
}
void Preorder(Node *root)
{
if(root == NULL) return ;
printf("%d ", root->key);
if(root->lchild != NULL) inorder(root->lchild);
if(root->rchild != NULL) inorder(root->rchild);
return ;
}
void inorder(Node *root)
{
if(root == NULL) return ;
if(root->lchild != NULL) inorder(root->lchild);
printf("%d ", root->key);
if(root->rchild != NULL) inorder(root->rchild);
return ;
}
int main()
{
Node *root = NULL;
#define MAX_INT 20
int op = 0;
int key = 0;
int i;
for(i = 0; i < MAX_INT; i++)
{
scanf("%d %d", &op, &key);
switch(op)
{
case 1 : root = insert_Node(root, key); break;
case 2 : root = earse_Node(root, key); break;
default : break;
}
inorder(root);
}
clear(root);
return 0;
}
总结:二叉搜索树最好情况是以O(logn)的时间复杂度来插入删除元素,如果插入的都属有序的元素那么该复杂度还是O(n)级别,此时这颗二叉树就会退化成链表,具体如何才能解决这种情况,过一阵会更新平衡二叉排序树(AVL_TREE)。