二叉树排序树,又称二叉搜索树、二叉查找树,顾名思义,从此树的一个结点开始依次取出后面结点的数据,取出的数据列是有序的。那么问题来了,二叉树不像线性表那样可以很直观的进行逻辑排序算法考量。二叉树作为非线性结构,必须靠一种特定的规则来对二叉树进行排序。这里我们一般用中序遍历进行有序排列。啥意思呢,就是一个二叉树按中序遍历依次取出的数据是从小到大的,就认为它是二叉排序树。也就是说,从根节点开始的每个子树,左孩子<根<右孩子,也就是说,它本身就是一种二分查找算法,好了不多赘述。下面开始实战。
本文对二叉排序树进行的操作主要通过二叉树的链式存储进行,先定义结构:
//设计结点
typedef struct TreeNode
{
int data;
struct TreeNode *left;
struct TreeNode *right;
}TreeNode;
先序和后序的操作可以参考之前的二叉树链式存储那一篇中有提到,这里只写中序。
创建结点
//创建结点
TreeNode *create_node(int data)
{
TreeNode *node=malloc(sizeof(TreeNode));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
中序
//中序
void midorder(TreeNode *root)
{
if(NULL==root) return;
midorder(root->left);
printf("%d ",root->data);
midorder(root->right);
}
插入
void _insert(TreeNode **root,TreeNode *node)
{
if(NULL==*root)
{
*root=node;
return;
}
if(node->data<(*root)->data)
_insert(&(*root)->left,node);
else _insert(&(*root)->right,node);
}
//插入 (重点)
void insert_tree(TreeNode **root,int data)
{
_insert(root,create_node(data));
}
查找
//查找
bool query_tree(TreeNode *root,int data)
{
if(NULL==root) return false;
if(data==root->data) return true;
if(data<root->data) return query_tree(root->left,data);
else return query_tree(root->right,data);
}
密度
//密度
int num_tree(TreeNode *root)
{
if(NULL==root) return 0;
return num_tree(root->left)+num_tree(root->right)+1;
}
高度
//高度
int high_tree(TreeNode *root)
{
if(NULL==root) return 0;
int lh=high_tree(root->left);
int rh=high_tree(root->right);
return lh>rh?lh+1:rh+1;
}
销毁
//销毁
void destroy_tree(TreeNode *root)
{
if(NULL==root) return;
destroy_tree(root->left);
destroy_tree(root->right);
free(root);
}
按中序访问
bool _access(TreeNode *root,int *k,size_t index,int *ptr)
{
if(NULL==root) return false;
bool lflag=_access(root->left,k,index,ptr);
if(*k++==index)
{
*ptr=root->data;
return true;
}
bool rflag=_access(root->right,k,index,ptr);
return lflag||rflag;
}
//访问 按中序
bool access_tree(TreeNode *root,size_t index,int *ptr)
{
int k=0;
return _access(root,&k,index,ptr);
}
删除
//删除
bool del_tree(TreeNode **root,int data)
{
if(NULL==*root) return false;
if((*root)->data==data)
{
TreeNode *temp=*root;
*root=temp->left;
if(temp->right) _insert(root,temp->right);
free(temp);
return true;
}
if(data<(*root)->data) return del_tree(&(*root)->left,data);
else return del_tree(&(*root)->right,data);
}
判断是否平衡(左右子树高度差不大于1),先介绍,后面会详细讲平衡树
//判断是否平衡(左右子树高度差不超过1)
bool isAVL_tree(TreeNode *root)
{
if(NULL==root) return true;
int lh=high_tree(root->left);
int rh=high_tree(root->right);
return abs(lh-rh)<=1 && isAVL_tree(root->left) && isAVL_tree(root->right);
}
基本运算写完了,下面测试:
int main(int argc,const char* argv[])
{
TreeNode *root=NULL;
for(int i=0;i<10;i++)
{
int data=rand()%100;
insert_tree(&root,data);
}
preorder(root);
printf("\n");
midorder(root);
printf("\n");
del_tree(&root,35);
midorder(root);
printf("\n");
return 0;
}
over