二叉排序树——理解与实现

来源:互联网 发布:免费笑话api数据接口 编辑:程序博客网 时间:2024/06/03 19:22

转载请注明t1234xy4 原创:http://blog.csdn.net/t1234xy4/article/details/51570916
二叉树的基本操作:
创建:二叉树的创建就是插入一个节点
查找
深度
遍历
删除节点

下面我们简单的来分析:
一、插入节点
有递归实现与非递归,个人建议用非递归。插入节点的数量很大,树的深度也很大的时候,使用递归可能导致函数调用的递归栈溢出。总的来说,非递归的健壮性要强于递归。

步骤分解:
1、查找插入节点处;
2、插入节点;
先给出递归的实现:

void InsertBST(BinaryTreeNode** root,int key){    if(root == NULL)  return ;    if(*root == NULL)    {        BinaryTreeNode* pNode = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));        if(pNode == NULL) return ;        pNode->m_Value  = key;        pNode->m_pLeft = NULL;        pNode->m_pRight = NULL;        *root = pNode;        return ;    }    if( key < (*root)->m_Value)        InsertBST( &((*root)->m_pLeft),key);    else if(key > (*root)->m_Value)        InsertBST( &((*root)->m_pRight),key);    else        return;}

步骤1:当root为空的时候,则为root节点;当root不为空时,利用二叉排序树的性质:一个节点的左子树都小于节点值,右子树都大于节点值。直到找为NULL的节点位置
步骤2:在步骤1中,需要使用两个指针,pRootNext用于指向需要插入的位置,pRoot用于指向pRootNext的父节点。然后可以通过生成节点插入到root树中。
插入的非递归实现:

void InsertBinarySortTree(BinaryTreeNode** root,int value){    if(root==NULL) return ;      if(*root == NULL)    {        BinaryTreeNode* pNode = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));        if(pNode == NULL) return ;        pNode->m_Value  = value;        pNode->m_pLeft = NULL;        pNode->m_pRight = NULL;        *root = pNode;        return ;    }else if(root == NULL || *root == NULL)        return ;    BinaryTreeNode* pRoot = *root;    BinaryTreeNode* pRootNext = NULL;    if(pRoot->m_Value <value)        pRootNext = pRoot->m_pRight;    else if(pRoot->m_Value > value)        pRootNext = pRoot->m_pLeft;    else        return ;    while(pRootNext!=NULL)    {        pRoot = pRootNext;        if(pRootNext->m_Value > value)            pRootNext = pRootNext->m_pLeft;        else if(pRoot->m_Value < value)            pRootNext = pRootNext->m_pRight;        else            return ;    }    BinaryTreeNode* pNode = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));    if(pNode == NULL) return ;    pNode->m_Value  = value;    pNode->m_pLeft = NULL;    pNode->m_pRight = NULL;    if(pRoot->m_Value > value)        pRoot->m_pLeft = pNode;    else        pRoot->m_pRight = pNode;}

二、遍历
树的遍历使用递归很简单,当前我也没有写非递归的遍历,等下完了继续贴在下面,这里给出递归实现的先序遍历BinaryTreeDLR 和 中序遍历BinaryTreeLDR,通过这两个遍历,可以画出树的结构图,来检验自己的实现是否正确。
代码如下:

void BinaryTreeDLR(BinaryTreeNode* root){    if(root == NULL)    return ;     printf("%4d",root->m_Value);     BinaryTreeDLR(root->m_pLeft);     BinaryTreeDLR(root->m_pRight);}void BinaryTreeLDR(BinaryTreeNode* root){    if(root == NULL)    return ;     BinaryTreeDLR(root->m_pLeft);     printf("%4d",root->m_Value);     BinaryTreeDLR(root->m_pRight);}

三、深度
树的深度计算也很简单,使用递归的方法如下:

/*to be test:1:完全二叉树2:满二叉树3;空树4:只有根节点的二叉树*/int DeepOfBinaryTree(BinaryTreeNode *root){    if(root == NULL)        return 0;    int leftdeepth = DeepOfBinaryTree(root->m_pLeft);    int rightdeepth = DeepOfBinaryTree(root->m_pRight);    return (leftdeepth>rightdeepth)? (leftdeepth+1) : (rightdeepth+1);}

非递归的方法等实现了继续更新。

四、收索
利用二叉排序树的特性也十分容易得到代码:
递归与非递归代码如下:

/*to be test:1: 5 3 2 1 4 9 8 7      42: 5 3 2 1 4 9 8 7      63: 5 3 2 1 4 9 8 7      95: 5                    56: null                 4*/BinaryTreeNode* SearchBinaryTree(BinaryTreeNode* root,int key){    if(root==NULL)  return NULL;    if(key < root->m_Value)         SearchBinaryTree(root->m_pLeft,key);    else if(key > root->m_Value)        SearchBinaryTree(root->m_pRight,key);    else        return root;    return NULL;}/*to be test:1: 5 3 2 1 4 9 8 7      42: 5 3 2 1 4 9 8 7      63: 5 3 2 1 4 9 8 7      95: 5                    56: NULL                 4*/BinaryTreeNode* SearchBinaryTreeNoRecursion(BinaryTreeNode* root,int key){    if(root == NULL) return NULL;    BinaryTreeNode* pRoot;    pRoot = root;    while(pRoot!=NULL)    {        if(key < pRoot->m_Value)            pRoot->m_pLeft;        else if(key > pRoot->m_Value)            pRoot = pRoot->m_pRight;        else            return pRoot;    }    return NULL;}

五、删除
二叉排序树节点的删除比较复杂,是所有操作中最难与掌握的部分。步骤分解:
1、查找删除节点
2、判定待删除节点的类型
3、分类型删除节点
删除节点的类型分为:
1. 叶子节点
2. 只有左子树或者右子树的节点
3. 同时有左右子树的节点

三种情况:
叶子节点处理需要考虑:
1. 是根节点,且无叶子节点;
2. 不是根节点;
只有左或右子树的节点;
1. 是根节点,有一叶子节点;
2. 不是根节点;
同时有左右子树的节点:
查找后继节点,将后继节点与当前节点交换;然后转化为1、2情况。

/*to be test:1: 5 3 2 1 4 9 8 7      42: 5 3 2 1 4 9 8 7      63: 5 3 2 1 4 9 8 7      94: 5 3 2 1 4 9 8 7      35: 5 3 2 1 4 9 8 7      15: 5                    56: 5 6 7 8  7           57: NULL                 4*/void DeleteKeyOfBinaryTree(BinaryTreeNode** root,int key){    if(root==NULL || ((*root) == NULL) )        return ;    BinaryTreeNode* pRoot = *root;    BinaryTreeNode* pRootNext = pRoot;    while( pRootNext!=NULL )    {        if(key == pRootNext->m_Value)   break;        pRoot = pRootNext;        if(key > pRootNext->m_Value)            pRootNext = pRootNext->m_pRight;        else             pRootNext = pRootNext->m_pLeft;    }    if(pRootNext == NULL) return; //no key in Tree    //convert Node with Two children to Node with one or none     if(pRootNext->m_pLeft != NULL && pRootNext->m_pRight != NULL)    {        BinaryTreeNode* pPNext = pRootNext;        BinaryTreeNode* pNext = pRootNext->m_pRight;        while(pNext->m_pLeft!=NULL)        {            pPNext = pNext;            pNext = pNext->m_pLeft;        }        pRootNext->m_Value = pNext->m_Value;        pRootNext = pNext;        pRoot = pPNext;    }    //delete the node with zero child    if(pRootNext->m_pLeft == NULL && pRootNext->m_pRight == NULL)    {        if(pRootNext == (*root))            *root = NULL;        else            (pRootNext == pRoot->m_pLeft)? (pRoot->m_pLeft = NULL):(pRoot->m_pRight = NULL);        free(pRootNext);        return;    }    //delete the node with a child    if(pRootNext->m_pLeft == NULL || pRootNext->m_pRight == NULL)    {        if(pRoot == pRootNext) //key is the root value            (pRootNext->m_pLeft != NULL)?( (*root) = pRootNext->m_pLeft):((*root) = pRootNext->m_pRight);        else if(pRootNext == pRoot->m_pLeft) //only with the left child            (pRootNext->m_pLeft != NULL)?(pRoot->m_pLeft = pRootNext->m_pLeft):(pRoot->m_pLeft = pRootNext->m_pRight);        else //only with the right child            (pRootNext->m_pLeft != NULL)?(pRoot->m_pRight = pRootNext->m_pLeft):(pRoot->m_pRight = pRootNext->m_pRight);        free(pRootNext);        return;    }}

源码下载点:http://download.csdn.net/detail/t1234xy4/9539861

1 0
原创粉丝点击