二叉排序树

二叉排序树

简介:

一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。
[以上结果来自百度百科]
在这里插入图片描述
上图就是一个简单的二叉排序树

插入(添加)节点

假设我们有一个数组int arr[] = { 5,8,2,7,4,1,9,3,6,10 };现在我们要将这10个元素加入到一个二叉排序树中。即从第一个元素开始加入。

1.如果根节点为空,那么直接赋值即可。
2.如果根节点不为空,那么判断将要插入的数据与节点中的数据进行比较,如果当前节点的数据大于要插入的数据key,那么将指针指向当前节点的左,否则指向右,知道当前节点为空,进行赋值即可。
对于创建树的过程可以采用递归或者循环,以下代码都会进行演示

== 定义二叉排序树的节点==

typedef struct Node{
    int data;
    struct Node* pLeft;
    struct Node* pRight;
    }Tree;

二叉排序树的添加节点

递归创建

void CreateTree(Tree** p,int key)
{
    if(*p == NULL)
    {
    	(*p) = (Tree*)malloc(sizeof(Tree));
        (*p)->data = key;
        (*p)->pLetf = NULL;
        (*p)->pRight = NULL;
        return;
    }
    if((*p)->data > key)   
    {
    	CreateTree(&((*p)->pLeft),key);
    }
    else if((*p)->data < key)
    {
    	CreateTree(&((*p)->pRight),key));	 
    }
    else
    {
    	printf("data error!!!\n");
    	exit(0);  //直接退出程序
    	return ;
    }
} 

非递归创建

void CreateTree(Tree** p,int key)
{
	if(*p == NULL)
	{
	    (*p) = (Tree*)malloc(sizeof(Tree));
	    (*p)->data = key;
	    (*p)->pLeft = NULL;
	    (*p)->pRight = NULL;
	    return;
	}
	Tree* pNode = NULL;
	Tree* pMark = *p;
	pNode = (Tree*)malloc(sizeof(Tree));
	pNode->data = key;
	pNode->pLeft = NULL;
	pNode->pRight = NULL;
	while(pMark)
	{
	    if(pMark->data > key)
	    {
	    	if(pMark->pLeft == NULL)
	    	{
	    	    pMark-pLeft = pNode;
	    	    return;
	    	} 
	    	pMark = pMark->pLeft;
	    }
	    else if(pMark->data < key)
	    {
	    	if(pMark->pRight == NULL)
	    	{
	    	    pMark->pRight = pNode;
	    	    return;
	    	}
	    	pMark = pMark->pRight;
	    }
	    else 
	    {
	         printf("data error!!\n");
	     	 exit(0);  //直接退出程序
	         return ;
	    } 		
	}
}

二叉排序树的删除操作

二叉排序树的删除操作要麻烦一些,毕竟不像单链表那样遍历然后直接一个删除就可以了,二叉树排序树中要删除节点,首先要找到节点,然后判断节点的左右子树是否为空,如果为空说明他是叶子节点,就可以直接删除,但是,如果不是叶子节点呢,我们可以通过循环将它变成一个叶子节点就可以了。最后一定要主要指针的指向。

过程:

  1. 查找待删除元素的位置
  2. 判断是否是叶子节点
    2.1 如果是叶子节点,直接进行删除,并将该节点的父节点对应的指针置空。
    2.2 如果不是叶子节点,那么就找这个节点的左的最右,进行值的覆盖,然后删除这个左的最右就可以了。
void DeleteNode(Tree** p.int key)
{
    if(*p == NULL) return;
    //查找待删除节点
    Tree* pDel = *p;
    Tree* pNode = NULL;
    Tree* pMark = NULL;
    int flag = 0;  //判断是否找到待删除节点
    while(pDel)
    {
       if(pDel -> data > key)
       {
           pNode = pDel;  //pNode记录待删除节点的父节点
           pDel = pDel->pLeft;
       }
       else if(pDel->data < key)
       {
           pNode = pDel;
           pDel = pDel->pRight;
       }
       else 
       {
           falg = 1;   //代表找到了
           break;
       }
    }
    //如果没有找到直接return
    if(flag == 0)
    {
        printf("Not Find %d\n",key);
        return;
    }
    //有两个孩子
    if(pDel->pLeft != NULL && pDel->pRight != NULL)
    {
        pMark = pDel;
        pDel = pDel->pLeft;
        while(pDel->pRight)
        {
            pNode = pDel;  //pNode 存父亲
            pDel = pDel->pRight;
        }
        pMark->data = pDel->data;
     }
     //只有一个或零个孩子
     if(pNode == NULL)  //被删除节点是根节点
     {
         (*p) = pDel->pLeft ? pDel->pLeft : pDel->pRight;
         free(pDel);
         pDel = NULL;
         return;
      }
      if(pDel == pNode->pLeft)
      { //此时还没有对pDel进行删除,
      //只是将pNode与pDel之间断开,并更改pNode指针的指向
      //pDel的父节点指向pDel的孩子节点
          pNode->pLeft = pDel->pLeft ? pDel->pLeft : pDel->pRight;
      }
      else 
      {
          pNode->pRight = pDel->Left ? pDel->pLeft : pDel->pRight;
      }
       free(pDel);
       pDel = NULL;
 }
//上面只有一个或另个孩子的情况,由于经过有两个孩子的那段代码后,待删除节点只能有一个或者零个节点,不再存在两个节点的情况了。

以上就是二叉排序树的添加节点个删除节点,以上代码均在VS 2017环境下成功运行,若有差错请指出,先行谢过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值