数据结构之二叉树基本操作

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);
	}


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌上花开缓缓归以

你的鼓励将是我创作的最大动力,

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值