二叉搜索树实现—> 循环
#pragma once
#include <assert.h>
#include <stdio.h>
#include <malloc.h>
typedef int DataType;
typedef struct BSTreeNode
{
DataType _data;
struct BSTreeNode* _pLeft;
struct BSTreeNode* _pRight;
}BSTNode,*pBSTNode;
//二叉搜索树的创建
void bintree_create(pBSTNode* tRoot,DataType array[])
{
int index=0;
_bintree_create(tRoot,array,&index);
}
void _bintree_create(pBSTNode* tRoot,DataType array[],int* index)
{
assert(tRoot);
if('*' != array[*index] && '#'!=array[*index])
{
//根节点的创建
*tRoot=bintreenode_create(array[*index]);
//左子树的创建
++(*index);
_bintree_create(&(*tRoot)->_pLeft,array,index);
//右子树的创建
++(*index);
_bintree_create(&(*tRoot)->_pRight,array,index);
}
}
//节点的创建
pBSTNode bintreenode_create(DataType data)
{
pBSTNode pNewNode=NULL;
pNewNode=(pBSTNode)malloc(sizeof(BSTNode));
if(NULL == pNewNode)
{
assert(pNewNode);
return NULL;
}
pNewNode->_data=data;
pNewNode->_pLeft=NULL;
pNewNode->_pRight=NULL;
return pNewNode;
}
//节点的查找
pBSTNode Is_bstNode(pBSTNode tRoot,DataType data)
{
if(NULL==tRoot)
return NULL;
if(data==tRoot->_data)
return tRoot;
else if(data<tRoot->_data)
return Is_bstNode(tRoot->_pLeft,data);
else if(data>tRoot->_data)
return Is_bstNode(tRoot->_pRight,data);
return NULL;
}
//节点的插入
void insert_bintreeNode(pBSTNode* tRoot,DataType data)
{
pBSTNode pCur=*tRoot,parent=NULL;
//1、树为空,则直接插入?
if(NULL==pCur)
{
pCur=bintreenode_create(data);
return;
}
//2、树不空,按二叉搜索树性质查找插入位置,插入新节点?
while (pCur)
{
if(data>pCur->_data)
{
parent=pCur;
pCur=pCur->_pRight;
}
else if(data<pCur->_data)
{
parent=pCur;
pCur=pCur->_pLeft;
}
else
return;
}
if(data>parent->_data)
parent->_pRight=bintreenode_create(data);
else
parent->_pLeft=bintreenode_create(data);
}
//节点的删除
void delete_bstNode(pBSTNode* tRoot,DataType data)
{
//找待删除节点位置
pBSTNode pParent=*tRoot,pCur=*tRoot;
if(NULL==pCur)
return;
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->_pRight)
{
//pCur是根节点
if((*tRoot)==pCur)
*tRoot=pCur->_pLeft;
else
{
//待删节点是双亲节点的左孩子
if(pParent->_pLeft==pCur)
pParent->_pLeft=pCur->_pLeft;
else
pParent->_pRight=pCur->_pLeft;
}
}
//要删除的结点只有右孩子结点
else if(NULL==pCur->_pLeft)
{
//pCur是根节点
if((*tRoot)==pCur)
*tRoot=pCur->_pRight;
else
{
//待删节点是双亲节点的左孩子
if(pParent->_pLeft==pCur)
pParent->_pLeft=pCur->_pRight;
else
pParent->_pRight=pCur->_pRight;
}
}
//要删除的结点左右孩子结点均存在
else
{
pBSTNode pDel=pCur->_pRight;
pParent=pCur;
//在双亲节点的左子树找最大的节点或者在右子树中找最小的节点
while (pDel->_pLeft)
{
pParent=pDel;
pDel=pDel->_pLeft;
}
pCur->_data=pDel->_data;
//替换节点的右子树存在
if(pDel->_pRight)
pParent->_pRight=pDel->_pRight;
pCur=pDel;
}
free(pCur);
pCur=NULL;
}
递归实现二叉搜索树中查找、插入和删除方法
//二叉搜索树的创建
void bintree_create(pBSTNode* tRoot,DataType array[])
{
int index=0;
_bintree_create(tRoot,array,&index);
}
void _bintree_create(pBSTNode* tRoot,DataType array[],int* index)
{
assert(tRoot);
if('*' != array[*index] && '#'!=array[*index])
{
//根节点的创建
*tRoot=bintreenode_create(array[*index]);
//左子树的创建
++(*index);
_bintree_create(&(*tRoot)->_pLeft,array,index);
//右子树的创建
++(*index);
_bintree_create(&(*tRoot)->_pRight,array,index);
}
}
//节点的创建
pBSTNode bintreenode_create(DataType data)
{
pBSTNode pNewNode=NULL;
pNewNode=(pBSTNode)malloc(sizeof(BSTNode));
if(NULL == pNewNode)
{
assert(pNewNode);
return NULL;
}
pNewNode->_data=data;
pNewNode->_pLeft=NULL;
pNewNode->_pRight=NULL;
return pNewNode;
}
//节点的查找
pBSTNode Is_bstNode(pBSTNode tRoot,DataType data)
{
if(NULL==tRoot)
return NULL;
if(data==tRoot->_data)
return tRoot;
else if(data<tRoot->_data)
return Is_bstNode(tRoot->_pLeft,data);
else if(data>tRoot->_data)
return Is_bstNode(tRoot->_pRight,data);
return NULL;
}
//节点的插入
void insert_bintreeNode(pBSTNode* tRoot,DataType data)
{
//1、树为空,则直接插入?
if(NULL==(*tRoot))
{
*tRoot=bintreenode_create(data);
return;
}
//2、树不空,按二叉搜索树性质查找插入位置,插入新节点?
if(data > (*tRoot)->_data)
insert_bintreeNode(&((*tRoot)->_pRight),data);
else
insert_bintreeNode(&((*tRoot)->_pLeft),data);
}
//节点的删除
void delete_bstNode(pBSTNode* tRoot,DataType data)
{
//找待删除节点位置
if(NULL==(*tRoot))
return;
if(data > (*tRoot)->_data)
delete_bstNode(&(*tRoot)->_pRight,data);
else if(data < (*tRoot)->_data)
delete_bstNode(&(*tRoot)->_pLeft,data);
else
{
pBSTNode pDel=*tRoot;
//要删除的结点右孩子为空(包括无左右孩子)
if(NULL==pDel->_pRight)
{
*tRoot=pDel->_pLeft;
free(pDel);
}
//要删除的结点只有右孩子结点
else if(NULL==pDel->_pLeft)
{
*tRoot=pDel->_pRight;
free(pDel);
}
//要删除的结点左右孩子结点均存在
else
{
pDel=pDel->_pRight;
while (pDel->_pLeft)
pDel=pDel->_pLeft;
(*tRoot)->_data=pDel->_data;
//现在转变成删替代节点pDel
delete_bstNode(&(*tRoot)->_pRight,pDel->_data);
}
}
}
//中序遍历
void MidOrder(pBSTNode tRoot)
{
if(NULL==tRoot)
return;
MidOrder(tRoot->_pLeft);
printf("%d ",tRoot->_data);
MidOrder(tRoot->_pRight);
}
//销毁二叉搜索树(后序)
void DestroyBSTree(pBSTNode* tRoot)
{
if(NULL==(*tRoot))
return;
DestroyBSTree(&(*tRoot)->_pLeft);
DestroyBSTree(&(*tRoot)->_pRight);
free(*tRoot);
}
整理二叉搜索树中的应用
1. 判断一个单词是否拼写正确
2. 请模拟实现一个简单的字典
typedef struct pair
{
char* _word;
char* _Chinese;
}pair;
typedef pair* DataType;
创建一个二叉搜索树,数据域就保存DataType;要想更准确的查词,就要保证这个二叉树里已经存了足够多的“pair”;在查词时,将word与pair->_word比较.
- log文件中有许多异常重复的IP地址,请统计出每个异常IP出现了多少
次?
typedef struct IP
{
int _ip;
int _count; //用来记录当前ip出现的次数
}
将每个ip向二叉树里插入,当遇到相同的ip时,就将对应ip的count加1;当插入完成时,就可以知道每个ip的重复次数。
分析二叉搜索树性能
插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的
性能。
对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平
均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数
越多
但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同
结构的二叉搜索树
最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:
最差情况下,二叉搜索树退化为单支树,其平均比较次数为: