C++中的二叉树问题(二叉树进阶)

1. 内容安排说明
二叉树在前面 C 数据结构阶段已经讲过,本节取名二叉树进阶是因为:
1. map set 特性需要 先铺垫二叉搜索树,而二叉搜索树也是一种树形结构
2. 二叉搜索树的特性了解,有助于更好的理解 map set 的特性
3. 二叉树中部分面试题稍微有点难度 ,在前面讲解 大家不容易接受 ,且时间长容易忘
4. 有些 OJ 题使用 C 语言方式实现比较麻烦,比如有些地方要返回动态开辟的二维数组,非常麻
烦。
因此本节借二叉树搜索树,对二叉树部分进行收尾总结。
2. 二叉搜索树
2.1 二叉搜索树概念
二叉搜索树又称二叉排序树,它或者是一棵空树 ,或者是具有以下性质的二叉树 :
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树

 

2.2 二叉搜索树操作
1. 二叉搜索树的查找
a 、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b 、最多查找高度次,走到到空,还没找到,这个值不存在。
2. 二叉搜索树的插入
插入的具体过程如下:
a. 树为空,则直接新增节点,赋值给 root 指针
b. 树不空,按二叉搜索树性质查找插入位置,插入新节点
1. ** 二叉搜索树的删除
首先查找元素是否在二叉搜索树中,如果不存在,则返回 , 否则要删除的结点可能分下面四种情
况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
看起来有待删除节点有 4 中情况,实际情况 a 可以与情况 b 或者 c 合并起来,因此真正的删除过程
如下:
情况 b :删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点 -- 直接删除
情况 c :删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点 -- 直接删除
情况 d :在它的右子树中寻找中序下的第一个结点 ( 关键码最小 ) ,用它的值填补到被删除节点
中,再来处理该结点的删除问题 -- 替换法删除
2.3 二叉搜索树的实现
template<class T>
struct BSTNode
{
 BSTNode(const T& data = T())
   : _pLeft(nullptr) , _pRight(nullptr), _data(data)
 {}
 BSTNode<T>* _pLeft;
 BSTNode<T>* _pRight;
 T _data;
};
template<class T>
class BSTree
{
 typedef BSTNode<T> Node;
 typedef Node* PNode;
public:
 BSTree(): _pRoot(nullptr)
 {}
 // 同学们自己实现,与二叉树的销毁类似
 ~BSTree();
 // 根据二叉搜索树的性质查找:找到值为data的节点在二叉搜索树中的位置
 PNode Find(const T& data);
 bool Insert(const T& data)
 {
 // 如果树为空,直接插入
 if (nullptr == _pRoot)
 {
 _pRoot = new Node(data);
 return true;
 }
 // 按照二叉搜索树的性质查找data在树中的插入位置
 PNode pCur = _pRoot;
 // 记录pCur的双亲,因为新元素最终插入在pCur双亲左右孩子的位置
 PNode pParent = nullptr;
 while (pCur)
 {
 pParent = pCur;
 if (data < pCur->_data)
pCur = pCur->_pLeft;
 else if (data > pCur->_data)
 pCur = pCur->_pRight;  // 元素已经在树中存在
 else
 return false;
 }
 // 插入元素
 pCur = new Node(data);
 if (data < pParent->_data)
 pParent->_pLeft = pCur;
 else
 pParent->_pRight = pCur;
 return true;
 }
 bool Erase(const T& data)
 {
 // 如果树为空,删除失败
 if (nullptr == _pRoot)
 return false;
 // 查找在data在树中的位置
 PNode pCur = _pRoot;
 PNode pParent = nullptr;
 while (pCur)
 {
 if (data == pCur->_data)
 break;
 else if (data < pCur->_data)
 {
 pParent = pCur;
 pCur = pCur->_pLeft;
 }
 else
 {
 pParent = pCur;
 pCur = pCur->_pRight;
 }
 }
 // data不在二叉搜索树中,无法删除
 if (nullptr == pCur)
 return false;
 // 分以下情况进行删除,同学们自己画图分析完成
 if (nullptr == pCur->_pRight)
 {
 // 当前节点只有左孩子或者左孩子为空---可直接删除
 }
 else if (nullptr == pCur->_pRight)
 {
 // 当前节点只有右孩子---可直接删除
 }
 else
 {
  // 当前节点左右孩子都存在,直接删除不好删除,可以在其子树中找一个替代结点,
比如:
 // 找其左子树中的最大节点,即左子树中最右侧的节点,或者在其右子树中最小的节
点,即右子树中最小的节点
 // 替代节点找到后,将替代节点中的值交给待删除节点,转换成删除替代节点
 }
 return true;
 }
// 同学们自己实现
 void InOrder();
private:
 PNode _pRoot;
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在DevC++实现二叉树的遍历可以通过递归或者使用栈来实现。下面是两种常见的二叉树遍历方法的示例代码: 1. 前序遍历(Preorder Traversal):先访问根节点,然后递归地遍历左子树和右子树。 ```c #include <stdio.h> #include <stdlib.h> // 二叉树结点的定义 struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; }; // 前序遍历函数 void preorderTraversal(struct TreeNode* root) { if (root == NULL) { return; } printf("%d ", root->data); // 访问根节点 preorderTraversal(root->left); // 递归遍历左子树 preorderTraversal(root->right); // 递归遍历右子树 } int main() { // 构建二叉树 struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->data = 1; root->left = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->left->data = 2; root->left->left = NULL; root->left->right = NULL; root->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->right->data = 3; root->right->left = NULL; root->right->right = NULL; // 前序遍历二叉树 printf("Preorder Traversal: "); preorderTraversal(root); return 0; } ``` 2. 序遍历(Inorder Traversal):先递归地遍历左子树,然后访问根节点,最后递归地遍历右子树。 ```c #include <stdio.h> #include <stdlib.h> // 二叉树结点的定义 struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; }; // 序遍历函数 void inorderTraversal(struct TreeNode* root) { if (root == NULL) { return; } inorderTraversal(root->left); // 递归遍历左子树 printf("%d ", root->data); // 访问根节点 inorderTraversal(root->right); // 递归遍历右子树 } int main() { // 构建二叉树 struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->data = 1; root->left = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->left->data = 2; root->left->left = NULL; root->left->right = NULL; root->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->right->data = 3; root->right->left = NULL; root->right->right = NULL; // 序遍历二叉树 printf("Inorder Traversal: "); inorderTraversal(root); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值