1,二叉树的定义:
typedef struct node
{
int data;
struct node *lchild;
struct node *rchild;
}Node;
typedef struct { //树根
Node* root;
} Tree;
注:二叉树创建为什么要用二级指针???
调用者的变量需要被修改内容,这里是root(指向Tree类型的指针),Tree需要指向一个新插入的节点,也就是需要修改root的值。所以 应该传入指向root的地址。这样在被调用的函数中,对Tree的操作等价于操作root。否则Tree如果是和root类型一样的Node类型 的指针,和root位于两个不同的内存,Tree只是被初始化为root的值,之后对Node的操作不会影响root。
2,二叉树的创建
void insert(Tree* tree, int value)//创建树
{
//node尾插入节点
Tree* node=(Tree*)malloc(sizeof(Tree));//创建一个节点
node->data = value;
node->left = NULL;
node->right = NULL;
if (tree->root == NULL)//判断树是不是空树
{
tree->root = node;
}
else {//不是空树
Node* temp = tree->root;//从树根开始
while (temp != NULL)
{
if (value < temp->data)//小于就进左儿子
{
if (temp->left == NULL)
{
temp->left = node;
return;
}
else {//继续判断
temp = temp->left;
}
}
else {//否则进右儿子
if (temp->right == NULL)
{
temp->right = node;
return;
}
else {//继续判断
temp = temp->right;
}
}
}
}
return;
}
3,二叉树的遍历
//中序
void InOrderTree(Tree root) {
if (root == NULL) {
return;
}
InOrderTree(root->left);
printf("%d ", root->data);
InOrderTree(root->right);
}
//先序
void PreOrderTree(Tree root) {
if (root == NULL) {
return;
}
printf("%d ", root->data);
PreOrderTree(root->left);
PreOrderTree(root->right);
}
//后序
void PostOrderTree(Tree root) {
if (root == NULL) {
return;
}
PostOrderTree(root->left);
PostOrderTree(root->right);
printf("%d ", root->data);
}
4,二叉树关键字的查找
//非递归
Tree SearchBSTree( Tree pBST,int key) //版本1
{
while(NULL != pBST && key != pBST ->data)
{
if(key < pBST ->data)
pBST = pBST ->pLchild;
else
pBST = pBST ->pRchild ;
}
return pBST;
}
//递归
Tree SearchBSTree(Tree pBST,int key) //版本2
{
if(NULL == pBST)
return NULL;
else if(key < pBST ->data)
return SearchBSTree(pBST ->pLchild,key);
else if(key > pBST ->data)
return SearchBSTree(pBST ->pRchild,key);
else
return pBST;
}
5,二叉树的深度
int maxDepth(Tree root) {
if (root == NULL) {
return 0;
}
else {
int maxLeft = maxDepth(root->left);
int maxRight = maxDepth(root->right);
if (maxLeft > maxRight) {
return 1 + maxLeft;
}
else {
return 1 + maxRight;
}
}
}
6,二叉树节点的删除
void DeleteBynum(Tree bt,int key)
{
Tree L,LL; //在删除左右子树都有的结点时使用;
Tree p=bt;
Tree parent=bt;
int child=0; //0表示左子树,1表示右子树;
if(!bt) //如果排序树为空,则退出;
return ;
while(p) //二叉排序树有效;
{
//1,叶结点(左右子树都为空);
if(p->data==key)
{
if(!p->lchild&&!p->rchild)
{
if(p==bt) //被删除的结点只有根结点;
free(p);
else if(child==0)
{
parent->lchild=NULL; //设置父结点左子树为空;
free(p); //释放结点空间;
}
else //父结点为右子树;
{
parent->rchild=NULL; //设置父结点右子树为空;
free(p); //释放结点空间;
}
}
//2,左子树为空,右子树不为空;
else if(!p->lchild)
{
if(child==0) //是父结点的左子树;
parent->lchild=p->rchild;
else //是父结点的右子树;
parent->rchild=p->rchild;
free(p); //释放被删除的结点;
}
//3,右子树为空,左子树不为空;
else if(!p->rchild)
{
if(child==0) //是父结点的左子树;
parent->lchild=p->lchild;
else //是父结点的右子树;
parent->rchild=p->lchild;
free(p); //释放被删除的结点;
}
//4,左右子树都不为空
else
{
LL=p; //保存左子树的结点;
L=p->rchild; //从当前结点的右子树进行查找;
if(L->lchild) //左子树不为空;
{
LL=L;
L=L->lchild; //查找左子树;
p->data=L->data; //将左子树的数据保存到被删除结点;
LL->lchild=L->lchild; //设置父结点的左子树指针为空;
for(;L->lchild;L=L->lchild);
L->lchild=p->lchild;
p->lchild=NULL;
}
else
{
p->data=L->data;
LL->rchild=L->rchild;
}
}
p=NULL;
}
else if(key<p->data) //需删除记录的关键字小于结点的数据;
{
//要删除的结点p是parent的左子树;
child=0; //标记在当前结点左子树;
parent=p;//保存当前结点作为父结点;
p=p->lchild; //查找左子树;
}
else //需删除记录的关键字大于结点的数据;
{
//要删除的结点p是parent的右子树;
child=1; //标记在当前结点右子树查找;
parent=p; //保存当前结点作为父结点;
p=p->rchild; //查找右子树;
}
}
}
7,叶子节点个数统计
int LeafNodeNum(t Tree root)
{
if (root == NULL) {
return 0;
}
if (root->left == NULL&&root->right == NULL) {
return 1;
}
else {
return LeafNodeNum(root->left) + LeafNodeNum(root->right);
}