数据结构—二叉搜索数

本文介绍了二叉树的概念,重点讲解了二叉搜索树的特点,包括如何进行查找、插入和删除操作。通过递归和非递归方式遍历二叉搜索树,并给出了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.二叉树

二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2^{i-1}个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_2,则n_0=n_2+1。
一棵深度为k,且有2^k-1个节点称之为满二叉树;深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为完全二叉树。

2.搜索二叉树

若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

3.二叉树的递归与非递归遍历以及层序遍历

void PrintPreorderTree(TreeNode* root)//前序遍历递归
{
if (root != NULL)
{
    cout << root->val;
    PrintPreorderTree(root->_left);
    PrintPreorderTree(root->_right);
}
}
void PrintInoderTree(TreeNode* root)//中序遍历递归
{
if (root != NULL)
{
    PrintInoderTree(root->_left);
    cout << root->val;
    PrintInoderTree(root->_right);
}
}
void PostorderTree(TreeNode*root)//后序遍历递归
{
if (root != NULL)
{
    PostorderTree(root->_left);
    PostorderTree(root->_right);
    cout << root->val;
}
}
void levelorderTree(TreeNode* root)//层序遍历利用队列
{
queue<TreeNode*> q;
if (root)
q.push(root);
while (!q.empty())
{
    TreeNode*front = q.front();
    cout << front->val;
    q.pop();
    if (front->_left)
    {
        q.push(front->_left);
    }
    if (front->_right)
    {
        q.push(front->_right);
    }
}

cout << endl;
}
void PostorderNonR(TreeNode*root)//后序遍历非递归
{
if (root == NULL)
    return;
stack<TreeNode*> s;
TreeNode*cur = root;
TreeNode*prev = NULL;
while (cur || !s.empty())
{
    while (cur)
    {
        s.push(cur);
        cur = cur->_left;
    }
    TreeNode* top = s.top();
    if (top->_right == NULL || top->_right == prev)//第二个判断条件防止进入死循环
    {
        cout << top->val;
        prev = top;
        s.pop();
    }
    else


        cur = top->_right;



}
cout << endl;
}
void prevorderTreeNonR(TreeNode*root)//前序遍历非递归
{
if (root == NULL)
    return;
stack<TreeNode*> s;
TreeNode*cur = root;
while (!s.empty() || cur)
{
    while (cur)
    {
        cout << cur->val;
        s.push(cur);
        cur = cur->_left;
    }
    cur = s.top();
    s.pop();
    cur = cur->_right;
}
cout << endl;

}
void inorderNonR(TreeNode*root)//中序遍历非递归
{
if (root == NULL)
{
    return;
}
stack<TreeNode*>s;
TreeNode*cur = root;
while (cur || !s.empty())
{
    while (cur)
    {
        s.push(cur);
        cur = cur->_left;
    }
    cur = s.top();
    cout << cur->val;
    s.pop();
    cur = cur->_right;
}
cout << endl;
}

4.搜索二叉树的查找 插入 删除

bool Insert(TreeNode*root, const int &val)//插入

{
if (root == NULL)
{
TreeNode*Newroot = new TreeNode(val);
return true;
}
TreeNode*parent = NULL;
TreeNode*cur = root;
while (cur)
{
if (val > cur->val)
{
parent = cur;
cur = cur->_right;
}
else if (val < cur->val)
{
parent = cur;
cur = cur->_left;
}
else
return false;
}
TreeNode* newnode = new TreeNode(val);
if (val val)
{
parent->_left = newnode;
}
if (val> parent->val)
{
parent->_right = newnode;
}
return true;
}
TreeNode* Find(TreeNode*root, const int val)
{
if (root == NULL)
return NULL;
TreeNode*cur = root;
while (cur)
{
if (val > cur->val)
{
cur = cur->_right;
}
else if (val < cur->val)
{
cur = cur->_right;
}
else
{
return cur;
}
}
return NULL;
}
bool Remove(TreeNode*root, const int &val)//删除
{
if (root == NULL)
return true;
TreeNode*parent = NULL;
TreeNode*cur = root;
while (cur)
{
if (val > cur->val)
{
parent = cur;
cur = cur->_right;
}
else if (val < cur->val)
{
parent = cur;
cur = cur->_left;
}
else
{
//走到这里已经找到要删除的结点cur
//cur共有三种存在的情况,我们一一处理。
TreeNode*del = NULL;
if (cur->_left == NULL)//1.cur的左为空
{
if (parent == NULL)
{
root = cur->_right;
}
if (parent->_right == cur)
{
parent->_right = cur->_right;
}
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
}
else if (cur->_right == NULL)//2.cur的右为空。
{
if (parent == NULL)
{
root = cur->_left;
}
if (parent->_right == cur)
{
parent->_right = cur->_left;
}
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
}
else//3.cur的左右都不为空,这里我们用替换法,找到一个可以替换cur的值,将找到的结点删除,达到目的。
//最合适的值应该是cur的右子树的最左结点,满足大于cur的左子树且小于cur的右。
{
TreeNode *parent = cur;
TreeNode*subleft = cur->_right;
while (subleft->_left)
{
parent = subleft;
subleft = subleft->_left;
}
cur->val = subleft->val;
del = subleft;
if (parent->_left == subleft)
{
parent->_left = subleft->_right;
}
else
{
parent->_right = subleft->_right;
}
delete del;
return true;
}
}
}

}

### 关于 PTA 平台上二叉搜索树的相关练习题及其解法 #### 了解二叉搜索树的基础概念 在深入探讨具体的练习之前,重要的是要理解什么是二叉搜索树(BST)。这是一种特殊的二叉树,在这种树中,对于任意节点而言,左子树中的所有键值小于该节点的键值;右子树中的所有键值大于该节点的键值[^1]。 #### 构建二叉搜索树 构建BST的过程涉及按照特定顺序插入新元素。每当有新的值加入时,程序会从根部开始遍历整棵树直到找到合适的位置放置这个数。如果当前考察位置为空,则直接在此处创建一个新的叶子节点来容纳待插入的据项。这一过程不仅有助于掌握基本的操作技能,而且可以增强对数据结构内部机制的认识。 #### 寻找共同祖先问题 当面对诸如“求两个指定节点之间的最低公共祖先”的挑战时,一种有效的方法是从根向下追踪路径直至遇到任一目标节点为止,并记录沿途访问过的每一个节点作为候选者。接着继续探索另一条分支并重复上述动作。最终对比两条路线所遇见过的所有节点集合,其中最深的那个交集成员即是答案所在之处[^3]。 ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def lowestCommonAncestor(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': if not root or root == p or root == q: return root left_search_result = lowestCommonAncestor(root.left, p, q) right_search_result = lowestCommonAncestor(root.right, p, q) if left_search_result and right_search_result: return root elif left_search_result: return left_search_result else: return right_search_result ``` 此代码片段展示了如何实现寻找最小公共祖先的功能。它采用递归的方式分别检查左右两侧是否存在所需的目标节点p和q。一旦发现两者皆存在于不同方向之下,则说明当前处理的对象正是它们之间最近的一个共有前辈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值