二叉查找树的插入与有序输出

本文详细介绍了二叉查找树的基本概念、插入操作、删除操作以及如何通过二叉查找树实现有序输出和排序。包括二叉查找树的性质、操作复杂度分析以及具体代码实现。

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

二叉查找树:插入和有序输出

二叉查找树是常用的数据结构

  1. 二叉查找树根结点比左儿子大,比右儿子小(或等)
  2. 以任意结点为根节点的子树也满足上述规律

结点数为n,深度为h的二叉查找树的操作

以下操作时间复杂度均为O(h)

因为这些操作都是逐层下降,每层只停留一次
1. 元素值查找
2. 插入元素(该操作将且仅将新元素插入为叶节点)
3. 删除元素

二叉树遍历所有元素有序输出的复杂度为O(n)

因为从一个结点到下一个结点的时间间隔是常数

结点数n和深度h的关系涉及到平衡树

lg(n)hn

可以用二叉查找树实现排序

如本例所演示,逐个插入待排序元素,最后的输出结果是数组中的序列按升序打印
该种方法若输入随机化之后,得到接近二叉平衡树情况下,排序时间复杂度也是O(nlg(n))

二叉树插入和遍历的实现

#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef int elemtype;
struct bstreeNode
{
    elemtype data;
    bstreeNode * left;
    bstreeNode * right;
};
void insert(bstreeNode * & r, elemtype val)
{
    bstreeNode * p = r;
    bstreeNode * pp = NULL;
    while(p != NULL)
    {
        pp = p;
        if (val >= p->data)
        {
            p = p->right;
        }
        else
        {
            p = p->left;
        }
    }
    if(pp != NULL)
    {
        bstreeNode * pi = new bstreeNode;
        pi -> data = val;
        pi -> left = NULL;
        pi -> right = NULL; 
        if (pp -> data <= val)
        { 
            pp -> right = pi;
        }
        else
        {
            pp -> left = pi;
        }
    }   
}
bstreeNode * cretree(const vector<elemtype> & arr)
{
    bstreeNode * root = new bstreeNode;
    if( arr.size()>0 )
    {
        root -> data = arr.at(0); 
        root -> left = NULL;
        root -> right = NULL;
    }
    for(int i=1; i<arr.size(); i++)
    {
        insert(root, arr.at(i));
    }
    return root;
}
void destree(bstreeNode * & r)
{
    if( r != NULL)
    {
        destree( r -> left );
        destree( r -> right );
    }
    delete r;
}
void mttree(bstreeNode * root) //traversal tree
{
    if(root != NULL)
    {
        if( root -> left != NULL)
        {
            mttree( root -> left);
        }
        cout<< root->data <<" ";
        if ( root -> right != NULL)
        {
            mttree( root -> right);
        }
    }
}
int main()
{
    elemtype arr[] = {4, 52, 26, 4, 8, 1, 15, 3, 27, 108};
    vector<elemtype> vec(arr, arr+sizeof(arr)/sizeof(elemtype)); 
    bstreeNode * root = cretree(vec);
    mttree(root);
    cout<<endl;
    destree(root);
    return 0;
}
  1. debug 过程中发现 !r 和 r != NULL 效果不一样,值得注意
  2. insert 操作中原本使用的也是递归查找到对应的叶结点,同时开辟空间赋值插入:
void insert(bstreeNode * & r, elemtype val)
{
    bstreeNode * p = r;
    if(p == NULL)
    {
        bstreeNode * p = new bstreeNode;
        p -> data = val;
        p -> left = NULL;
        p -> right = NULL;
    }
    if(val >= p -> data )
    {
        p = p -> right;
        insert(pr, val);
    } 
    else
    {
        p = p -> left;
        insert(pl, val);
    }
}

该方法debug 过程中最多只能构建两个结点. 原因:父子关系丢失,树不能连接起来,因此每次插入最多只有2个结点. 需要在insert()函数中添加一个参数,指向当前子树根的父结点.
改用迭代之后会更接近 insert 的表达习惯,代码如上: 先找到插入点的位置,再对位置进行操作.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值