1. 二叉搜索树的概念
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值,若它的右子树不为空,则它右子树上所有节点的值都大于根节点的值,它的左右子树也分别为二叉搜索树。
2. 二叉搜索树实现---> 循环
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 PreOrder(BSTNode* pRoot);
// 销毁二叉搜索树
void DestroyBSTree(BSTNode** pRoot);
2. 二叉搜索树实现---> 循环
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 PreOrder(BSTNode* pRoot);
// 销毁二叉搜索树
void DestroyBSTree(BSTNode** pRoot);
#define _CRT_SECURE_NO_WARNINGS
#ifndef BsTree_h
#define BsTree_h
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int DataType;
typedef struct BsTreeNode{
struct BsTreeNode * pleft;
struct BsTreeNode * pright;
DataType data;
}BsTreeNode;
BsTreeNode *Buynode(DataType data){//获取一个新节点
BsTreeNode* pnewnode = NULL;
pnewnode = (BsTreeNode*)malloc(sizeof(BsTreeNode));
if (pnewnode == NULL){
assert(0);
return NULL;
}
pnewnode->data = data;
pnewnode->pleft = NULL;
pnewnode->pright = NULL;
return pnewnode;
}
void InitBsTree(BsTreeNode** proot){//初始化二叉搜索树
assert(proot);
*proot = NULL;
}
void InsertBsTree(BsTreeNode** proot, DataType data){//插入新节点
assert(proot);
BsTreeNode *pcur = *proot;
BsTreeNode *parent = *proot;
if (*proot == NULL){
*proot = Buynode(data);
}
else{
while (pcur){
if (data < pcur->data){
parent = pcur;
pcur = pcur->pleft;
}
else if (data>pcur->data){
parent = pcur;
pcur = pcur->pright;
}
else{
return;
}
}
if (data < parent->data){
parent->pleft = Buynode(data);
}
else{
parent->pright = Buynode(data);
}
}
}
void midorder(BsTreeNode *proot){//中序遍历二叉搜索树
if (proot){
midorder(proot->pleft);
printf("%d", proot->data);
midorder(proot->pright);
}
}
int FindBsTree(BsTreeNode *proot, DataType data){//查找值为data的节点
assert(proot);
BsTreeNode* pcur=proot;
while (pcur){
if (data < pcur->data){
pcur = pcur->pleft;
}
else if (data>pcur->data){
pcur = pcur->pright;
}
else{
printf("找到了!");
return pcur->data;
}
}
printf("未找到!");
}
void destoryBsTree(BsTreeNode**proot){//按照后序遍历来销毁二叉搜索树
assert(proot);
if (*proot){
destoryBsTree(&(*proot)->pleft);
destoryBsTree(&(*proot)->pright);
free((*proot));
*proot = NULL;
}
}
void delect(BsTreeNode**proot, DataType data){//删除任意位置上的节点
assert(proot);
if (*proot == NULL){
return;
}
BsTreeNode*pcur = *proot;
BsTreeNode* parent = *proot;
while (pcur){
if (data < pcur->data){
parent = pcur;
pcur = pcur->pleft;
}
else if (data>pcur->data){
parent = pcur;
pcur = pcur->pright;
}
else{
break;
}
}
if (NULL == pcur){
return;
}
else{
if (pcur->pright == NULL){//只有左孩子,或者是叶子结点
if (pcur == *proot){//如果要删除节点是根,要更新根节点
*proot = pcur->pleft;
}
else{//要删除节点不是根节点
if (pcur = parent->pleft){//要删除节点是双亲的左孩子
parent->pleft = pcur->pleft;
}
else if (pcur = parent->pright){//要删除节点是双亲的右孩子
parent->pright = pcur->pleft;
}
}
}
else if (pcur->pleft == NULL){//只有右孩子
if (pcur == *proot){
*proot = pcur->pright;
}
else{
if (pcur = parent->pleft){
parent->pleft = pcur->pright;
}
else if (pcur = parent->pright){
parent->pright = pcur->pright;
}
}
}
else{//左右孩子都有,在其右子树上找一个最小节点来替换删除
BsTreeNode* pdel = pcur->pright;
parent = pcur;//注意删除8的情况,8没有左子树,要将其parent更新
while (pdel->pleft){//查找最小节点(注意:查找的最小节点一定没有左孩子,也不可能是根)
parent = pdel;
pdel = pdel->pleft;
}
pcur->data = pdel->data;
if (pcur = parent->pleft){
parent->pleft = pcur->pright;
}
else if (pcur = parent->pright){
parent->pright = pcur->pright;
}
}
}
}
3. 递归实现二叉搜索树中查找、插入和删除方法
// 以递归方式实现二叉搜索树
void InitBSTree(BSTNode** pRoot);
BSTNode* FindBSTree(BSTNode* pRoot, DataType data);
int InsertBSTree(BSTNode** pRoot, DataType data);
int DeleteBSTree(BSTNode** pRoot, DataType data);
void PreOrder(BSTNode* pRoot);
void DestroyBSTree(BSTNode** pRoot);
int FindBsTree2(BsTreeNode *proot, DataType data){//递归查找
if (proot == NULL){
return 0;
}
else if (proot->data == data){
return 1;
}
else if (proot->data > data){
return FindBsTree2(proot->pleft, data);
}
else if (proot->data > data){
return FindBsTree2(proot->pright, data);
}
}
void InsertBsTree2(BsTreeNode** proot, DataType data){//递归插入
assert(proot);
if (NULL == *proot){
*proot = Buynode(data);
}
else{
if (data < (*proot)->data){
InsertBsTree(&(*proot)->pleft, data);
}
if (data >(*proot)->data){
InsertBsTree(&(*proot)->pright, data);
}
else
return;
}
}
//递归删除未写(对每个节点的处理相当于对根的处理)
#endif
3. 二叉搜索树中的应用
a.判断一个单词是否拼写正确
将单词集合放入二叉搜索树中,每个节点为char*类型,然后用strcmp进行查找,只要在单词集合中找到单词则认为拼写正确。
b.请模拟实现一个简单的字典
每个节点以键值对的方式来存储(<单词 中文含义>)底层就是个struct结构体。
c. log文件中有许多异常重复的ip地址,请统计每个异常ip出现了多少次
以键值对的方式来存储(<ip,count>),在这个二叉搜索树中来查找ip,没有则插入,有则count++.
4. 分析二叉搜索树性能
4. 分析二叉搜索树性能
插入和删除操作都必须先查找,最优的情况下,也就是二叉搜索树为完全二叉树,其查找的时间复杂度为树的高度:log2n,但最坏的情况下,也就是二叉搜索树退化为单支树,就相当于一个链表,其时间复杂度也退化成了o(n).
5. 了解平衡树AVL树和红黑树
5. 了解平衡树AVL树和红黑树
因此,两位俄罗斯数学家在1962年发明了一个解决上述问题的方法,当向二叉搜索树中插入新节点后,如果能保证每个节点左右子树高度之差的绝对值不超过1,即降低树的高度,从而减少平均搜索长度。红黑树是一科二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是red或者black,通过对任何一条从根节点到叶子结点简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似平衡,而且在实际应用中发现,红黑树性能确实比AVL树性能高。