二叉排序树——理解与实现
来源:互联网 发布:免费笑话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
- 二叉排序树——理解与实现
- 二叉排序树的实现与输出
- 二叉排序树的实现——java
- 二叉排序树——完整代码实现
- 二叉排序树的插入与查找实现
- 二叉排序树(C与Python分别实现)
- 二叉排序树——SDUT
- 2482——二叉排序树
- 查找——二叉排序树
- 动态查找—二叉排序树
- 大话数据结构—二叉排序树
- 二叉排序树实现
- 实现二叉排序树
- 实现二叉排序树
- 数据结构与算法Java版——二叉排序树
- 写二叉排序树的问题与指针的理解
- 查找与二叉排序树的建立与查找实现
- 二叉排序树的理解
- [递归]poj 1057 FILE MAPPING
- java中日期格式转换
- springMVC之Controller方法的返回值
- PL/SQL异常处理
- php二分查找法
- 二叉排序树——理解与实现
- ios学习资料
- android 爬坑之路
- GOLD SDK兼容第三方采集器补丁
- iOS学习- 12 绑定数组数据到Table View - Todo App
- java jdk 基础类
- C语言学习篇-8地址与指针
- Centos6.5 Nginx +Tomcat 集群搭建
- JavaScript--DOM编程核心