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);
3
. 递归实现二叉搜索树中查找、插入和删除方法
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; } } } }
// 以递归方式实现二叉搜索树
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树性能高。