二叉搜索树
二叉查找树(Binary Search Tree),(二叉搜索树 或 二叉排序树)它或者是一棵空树,
或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树。
二叉树实现:
二叉树及二叉树的基本操作(递归与非递归) - W_J_F_的博客 - CSDN博客 https://blog.csdn.net/W_J_F_/article/details/80408846
BinarySearchTree.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>
typedef int DataType;
typedef struct BSTreeNode
{
struct BSTreeNode* _pleft;
struct BSTreeNode* _pright;
DataType _data;
}BSTNode;
// 初始化二叉搜索树
void InitBSTree(BSTNode** pRoot);
// 插入值为data的元素
void InsertBSTree(BSTNode** pRoot, DataType data);
// 删除值为data的结点
void DeleteBSTree(BSTNode** pRoot, DataType data);
// 在二叉搜索树中查找值为data的结点
BSTNode* FindBSTree(BSTNode* pRoot, DataType data);
// 中序遍历二叉搜索树
void InOrder(BSTNode* pRoot);
// 销毁二叉搜索树
void DestroyBSTree(BSTNode** pRoot);
//
BSTNode* _FindBSTree(BSTNode* pRoot, DataType data);
int _InsertBSTree(BSTNode** pRoot, DataType data);
int _DeleteBSTree(BSTNode** pRoot, DataType data);
BInarySearchTree.c
#include"BinarySearchTree.h"
// 初始化二叉搜索树
void InitBSTree(BSTNode** pRoot)//改变指针的指向传二级指针
{
assert(pRoot);
*pRoot = NULL;
}
BSTNode* BuyNode(DataType data)
{
BSTNode* pNew = (BSTNode*)malloc(sizeof(BSTNode));
if (pNew == NULL)
{
assert(0);
return 0;
}
pNew->_data = data;
pNew->_pleft = NULL;
pNew->_pright = NULL;
return pNew;
}
// 插入值为data的元素
void InsertBSTree(BSTNode** pRoot, DataType data)
{
BSTNode* pParent = NULL;
BSTNode* pCur = NULL;
assert(pRoot);
if (*pRoot == NULL)//如果树是空的
{
*pRoot = BuyNode(data);
return;
}
//查找待插入位置
pCur = *pRoot;
while (pCur)
{
if (data < pCur->_data)
{
pParent = pCur;
pCur = pCur->_pleft;
}
else if (data > pCur->_data)
{
pParent = pCur;
pCur = pCur->_pright;
}
else
{
return;
}
}
//插入节点
pCur = BuyNode(data);
if (data > pParent->_data)
{
pParent->_pright = pCur;
}
else
{
pParent->_pleft = pCur;
}
}
// 删除值为data的结点
void DeleteBSTree(BSTNode** pRoot, DataType data)
{
//1:左右孩子为空,直接删除
//2:只有左孩子(1:是否有双亲,2:是双亲的左或右孩子)
//3:只有右孩子(1:是否有双亲,2:是双亲的左或右孩子)
//4:左右孩子均存在 》》找代替节点 1:左子树代替——最大元素
// 2:右子树代替——最小元素
// 》》将代替节点中的的数据交给待删除的节点
// 》》连接(待删除节点为其双亲的左或右孩子)
//找待删除节点在二叉搜索树的位置
BSTNode* pCur = *pRoot;
BSTNode* pParent = pCur;
while (pCur)
{
if (data == pCur->_data)
break;
else if (data > pCur->_data)
{
pParent = pCur;//记录双亲
pCur = pCur->_pright;
}
else
{
pParent = pCur;
pCur = pCur->_pleft;
}
}
if (NULL == pCur)
return;
//删除
if (NULL == pCur->_pleft)//只右有孩子||叶子
{
if (pCur == *pRoot)//无双亲
{
*pRoot = pCur->_pright;
}
else
{
if (pParent->_pleft == pCur)//待删除节点是双亲的左
{
pParent->_pleft = pCur->_pright;
}
else//待删除节点是双亲的右
pParent->_pright = pCur->_pright;
}
}
else if (NULL == pCur->_pright)//只有左孩子||叶子
{
if (pCur == *pRoot)
{
*pRoot = pCur->_pleft;
}
else
{
if (pParent->_pleft == pCur)
{
pParent->_pleft = pCur->_pleft;
}
else
{
pParent->_pright = pCur->_pleft;
}
}
}
else//左右孩子均存在
{
//4:左右孩子均存在 》》找代替节点 1:左子树代替——最大元素
// 2:右子树代替——最小元素
// 》》将代替节点中的的数据交给待删除的节点
// 》》连接(待删除节点为其双亲的左或右孩子)
BSTNode* pDel = pCur->_pright; //寻找右子树的最小结点
while (pDel->_pleft)
{
pParent = pDel;
pDel = pDel->_pleft;
}
pCur->_data = pDel->_data;
if (pDel == pParent->_pleft)//待删除节点可能含有右子树(已经找到最左)
{
pParent->_pleft = pDel->_pright;
}
else
{
pParent->_pright = pDel->_pright;
pCur = pDel;
}
}
free(pCur);
pCur = NULL;
}
// 在二叉搜索树中查找值为data的结点
BSTNode* FindBSTree(BSTNode* pRoot, DataType data)
{
assert(pRoot);
BSTNode* pCur = pRoot;
while (pCur)
{
if (data == pCur->_data)
return pCur;
else if (data > pCur->_data)
pCur = pCur->_pright;
else
pCur = pCur->_pleft;
}
return NULL;
}
// 中序遍历二叉搜索树
void InOrder(BSTNode* pRoot)
{
if (pRoot)
{
InOrder(pRoot->_pleft);
printf("%d->",pRoot->_data);
InOrder(pRoot->_pright);
}
}
// 销毁二叉搜索树
void DestroyBSTree(BSTNode** pRoot)
{
assert(pRoot);
if (*pRoot)
{
DestroyBSTree(&(*pRoot)->_pleft);
DestroyBSTree(&(*pRoot)->_pright);
free(*pRoot);
*pRoot = NULL;
}
}
递归
BSTNode* _FindBSTree(BSTNode* pRoot, DataType data)
{
if (pRoot == NULL)
{
return NULL;
}
else
{
if (data == pRoot->_data)
{
return pRoot;
}
else if (data > pRoot->_data)
{
return _FindBSTree(pRoot->_pleft,data);
}
else
{
return _FindBSTree(pRoot->_pright,data);
}
}
}
int _InsertBSTree(BSTNode** pRoot, DataType data)
{
assert(pRoot);
if (NULL == *pRoot)
{
*pRoot = BuyNode(data);
}
else
{
if (data > (*pRoot)->_data)
{
_InsertBSTree(&(*pRoot)->_pright, data);
}
else if (data < (*pRoot)->_pleft)
{
_InsertBSTree(&(*pRoot)->_pright, data);
}
else
{
return 0;
}
}
}
int _DeleteBSTree(BSTNode** pRoot, DataType data)
{
assert(pRoot);
if (NULL == *pRoot)
{
return 0;
}
else
{
if (data > (*pRoot)->_data)
{
_DeleteBSTree(&(*pRoot)->_pright,data);
}
else if (data < (*pRoot)->_data)
{
_DeleteBSTree(&(*pRoot)->_pleft,data);
}
else
{
//只有右孩子||叶子节点
BSTNode* pDel = *pRoot;
if (NULL == pDel->_pleft)
{
*pRoot = pDel->_pright;
free(pDel);
}
else if(NULL == pDel->_pright)//只有左子树||叶子
{
*pRoot = pDel->_pleft;
free(pDel);
}
else//左右子树
{
pDel = (*pRoot)->_pright;
while (pDel->_pleft)
{
pDel->_pleft;
}
(*pRoot)->_data = pDel->_data;
_DeleteBSTree(&(*pRoot)->_pright,pDel->_data);
}
}
}
}
test
#include"BinarySearchTree.h"
test()
{
int a[] = {5,4,6,9,0,2,1,8,7,3};
int i = 0;
BSTNode* pRoot;
InitBSTree(&pRoot);
for (;i < sizeof(a) / sizeof(a[0]);i++)
{
InsertBSTree(&pRoot,a[i]);
}
printf("InOrder: ");
InOrder(pRoot);
printf("\n");
DeleteBSTree(&pRoot, 5);
printf("InOrder: ");
InOrder(pRoot);
printf("\n");
DeleteBSTree(&pRoot, 7);
printf("InOrder: ");
InOrder(pRoot);
printf("\n");
}
int main()
{
test();
system("pause");
return 0;
}
二叉搜索树性能分析:
二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多
最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:
最差情况下,二叉搜索树退化为单支树,其平均比较次数为:
AVL树
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
它的左右子树都是AVL树
左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结
点,其高度可保持在O(lgn),平均搜索时间复杂度O(lg(n))
红黑树:
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,
可以是red或者black,通过对任何一条从根节点到叶子结点简单路径上的颜色来约束,
红黑树保证最长路径不超过最短路径的两倍,
因而近似平衡,而且在实际应用中发现红黑树性能确实比AVL树性能高
红黑树性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)