[数据结构]二叉查找树-基础版

基础信息:(摘自某度百科)
二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).


废话这么多。


逻辑结构

一棵二叉查找树满足一下几条性质。

对于任意节点:
1、其左子节点的键值小于其自身键值
2、其右子节点的键值大于其自身键值
3、任意节点可以代表一棵二叉查找树

如图即是一棵简单的bst(binary search tree):
简单的bst
根据其性质,我们又能总结出:

一棵bst的左节点的左节点的左节点。。。的左节点(最左节点)带有这棵树中的最小键值
同理,最右节点带有最大键值
一棵树中不允许带有两个相同键值的节点同时存在

由于数组过于占用空间,我打算用指针实现。
首先声明一个节点结构体。一个节点包括:

指向左子节点与右子节点的指针
键值
(可选)查询值
struct node{
    node *lchild,rchild;
    int key,value;
    node (int k,int v){key=k,val=v;}
    node(){}
};

现在我们来构建一棵树。
根据性质:任意节点可代表一棵二叉查找树,我们要实例化一个根节点。

class BST{
    node *root;
public:
};

一个数据结构所具有的基本素养(划掉)操作包括插入和查询操作。于是我们在BST类中添加如下insert()与query()。

class BST{
    node *root;
public:
    void insert(int key,int val);
    int query(int key);
};

具体实现

插入
1、递归版
递归查询的优点是代码量短,但对于刚刚接触递归的童鞋较难理解。
接下来的代码我将逐句解释。

void insert(node &*target,int key,int val){
//一定要注意取址符!!!!!
    if(!target){
        target=new node(key,val);
        return;//递归终止条件,如果当前节点为空,则创建一个新的节点
    }
    //只有对非空节点的访问能够执行到这里
    if(key>target->key)
        insert(target->rchild,key,val);
        //由于待插入键值大于当前结点,所以应该向右子节点插入
    else if(key<target->key)
        insert(target->lchild,key,val);
    else return;//插入的键值已经存在于当前的树中,假设这种情况不存在
}

2、非递归版
如果不用递归,代码会变得复杂一些。

void insert(int key,int val){
    node **scout=&root;
    while(*scout){
        if(key>*scout->key)scout=&(*scout->rchild);
        else scout=&(*scout->lchild);
    }
    *scout=new node(key,val);
}

查询
其实查询操作已经隐含在了插入中。

void query(int key,int val){
    node *scout=root;
    while(scout->key!=key){
        if(key>scout->key)scout=scout->rchild;
        else scout=scout->lchild;
    }
    return scout->val;
}

由于不需要修改节点信息,所以查询操作不需要取址符。
至此,一个二叉查找树诞生了。

class Tree{
    struct node{
        int key,val;
        node(int k,int v){key=k,val=v;}
        node(){}
    };
    node *root;
public:
    void insert(int key,int val){
        node **scout=&root;
        while(*scout){
            if(key>*scout->key)scout=&(*scout->rchild);
            else scout=&(*scout->lchild);
        }
        *scout=new node(key,val);
    }
    void query(int key,int val){
        node *scout=root;
        while(scout->key!=key){
            if(key>scout->key)scout=scout->rchild;
            else scout=scout->lchild;
        }
        return scout->val;
    }
};

实例化后就可以使用了
还可以进一步修改成模板类

template<typename KeyType,typename ValType>
class Tree{
    struct node{
        KeyType key;ValType val;
        node(KeyType k,ValType v){key=k,val=v;}
        node(){}
    };
    node *root;
public:
    void insert(KeyType key,ValType val){
        node **scout=&root;
        while(*scout){
            if(key>*scout->key)scout=&(*scout->rchild);
            else scout=&(*scout->lchild);
        }
        *scout=new node(key,val);
    }
    int query(KeyType key){
        node *scout=root;
        while(scout->key!=key){
            if(key>scout->key)scout=scout->rchild;
            else scout=scout->lchild;
        }
        return scout->val;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值