二叉排序树
二叉排序树(BST)又称二叉搜索树,其满足以下性质:
(1)若根节点的左子树非空,则左子树上的所有节点关键字均小于根节点的关键字。
(2)若根节点的右子树非空,则有子树上的所有节点关键字均大于根节点的关键字。
(3)根节点的左右子树本身又是一颗二叉排序树。
(4)二叉排序树的中序序列为递增有序序列。
(5)二叉有序树最左下的节点为最小的节点,最右下的节点为最大的节点。
二叉有序树的建立是采用链式存储结构。
结构体的定义:
typedef struct node
{
int key; //关键字
struct node* lchild, * rchild; //左右孩子指针
};
二叉排序树的插入:
BSTNode* InsertBST(BSTNode* bt, int k)
{
if (bt == NULL)
{
bt = (BSTNode*)malloc(sizeof(BSTNode)); //该节点为空则新建bt节点
bt->key = k;
bt->lchild = bt->rchild = NULL;
}
else if (k < bt->key) //插入左子树
{
bt->lchild = InsertBST(bt->lchild, k);
}
else if (k > bt->key) //插入右子树
{
bt->rchild = InsertBST(bt->rchild, k);
}
return bt; //返回插入后二叉排序树的根节点
}
二叉排序树的创建:
BSTNode* CreateBST(int a[], int n)
{
BSTNode* bt = NULL;
int i = 0;
while (i < n)
{
bt = InsertBST(bt, a[i]); //将关键字a[i]逐个插入到二叉排序树中
i++;
}
return bt;
}
二叉排序树的查找:
递归算法:
BSTNode* RECSearchBST(BSTNode* bt, int k)
{
if (bt == NULL || bt->key == k)
{
return bt; //若为空则为找到,若找到则返回在bt中关键字为k的节点
}
if (k < bt->key)
{
return SearchBST(bt->lchild, k); //在左子树中递归查找
}
else
{
return SearchBST(bt->rchild, k); //在右子树中递归查找
}
}
非递归算法:
BSTNode* SearchBST(BSTNode* bt, int k)
{
BSTNode* p = bt;
while (p != NULL)
{
if (p->key == k)break;
else if (k < p->key)
{
p = p->lchild;
}
else
{
p = p->rchild;
}
}
return p;
}
二叉排序树上进行查找的平均查找长度与其形态有关,其形态与关键字的输入顺序有关(即与排序二叉树的构建有关):
在含有 n 个关键字的集合中(n>0,所有关键字唯一)有 n!个关键字。
可构造出不同形态的排序二叉树有:
最坏的情况下二叉排序树会蜕化为一颗高度为 n 的单支树,其平均查找长度与单链表上的顺序查找相同即为(n+1)/2 此时的时间复杂度为O(n)。
最好的情况下二叉树形态比较均匀,与折半查找的判定树类似此时的时间复杂度为O(logn)。
故一颗含有 n 个节点的二叉排序树的查找算法的时间复杂度介于 O(logn) 与O(n)之间。
查找最大节点与最小节点:
int maxnode(BSTNode* p) //返回二叉树中最大节点的关键字
{
while (p->rchild != NULL)
p = p->rchild;
return p->key;
}
int minnode(BSTNode* p) //返回二叉树中最小节点的关键字
{
while (p->lchild != NULL)
p = p->lchild;
return p->key;
}
void maxminnode(BSTNode* p)
{
if (p != NULL)
{
if (p->lchild != NULL)
printf("最大节点为:%d\n",maxnode(p->lchild));
if (p->rchild != NULL)
printf("最小节点为:%d\n", minnode(p->rchild));
}
}