数据结构13—二叉搜索树,堆

数据结构13—二叉搜索树,堆

二叉树

二叉树的定义

  1. Binode的模版——递归定义法

    template <typename T> struct BinNode { 
        BinNodePosi(T) parent,lc,rc; //父节点及左、右孩子
        int height; int size(); T data;
        // 构造函数
        BinNode() :
        BinNodePosi(T) insertAsLC ( T const& ); //作为当前节点的左孩子插入新节点
        BinNodePosi(T) insertAsRC ( T const& ); //作为当前节点的右孩子插入新节点
        BinNodePosi(T) succ(); //取当前节点的直接后继
        template <typename VST> void travLevel ( VST& ); //子树层次遍历
        template <typename VST> void travPre ( VST& ); //子树先序遍历
        template <typename VST> void travIn ( VST& ); //子树中序遍历
        template <typename VST> void travPost ( VST& ); //子树后序遍历
     };
    
  2. Binode接口实现

    template <typename T>
    BinNodePosi(T)BinNode<T>::insertAsLC(T const& e)
    {return lc=new BinNode(e,this);}
    
    template <typename T>
    BinNodePosi(T)BinNode<T>::insertAsRC(T const& e)
    {return rc=new BinNode(e,this);}
    
    template <typename T>
    int BinNode<T>::size(){
    int s=1;
    if(lc) s += lc->size();
    if(rc) s +=rc->size();
    return s;
    }
    
  3. BinTree模版

    template<typename T> class BinTree{
    protected:
        int _size;
        BinNodePosi(T) _root;
        virtual int updateHeight(BinNodePosi(T)x);
        void updateHeightAbove(BinNodePosi(T)x);
    public:
        int size()const;
        bool empty()const{return !_root;}
        BinNodePosi(T) root()const {return _root;}
        /*...子树接入删除和分离接口...*/
        /*...遍历接口...*/
    }
    

二叉搜索树

二叉搜索树search
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 //这样函数定义的确会只返回二叉树的内容,而不能返回节点的地址
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
            if(root==NULL) return NULL;
            if(root->val==val)return root;
            else if(root->val<val) return searchBST(root->right,val);
            else return searchBST(root->left,val);
    }
};

测试用例举例:

[4,2,7,1,3]
2

image-20200424204911875

二叉搜索树的插入
递归

此递归代码和老师讲的稍微有所不同,需要返回的是整个树,也就是返回root节点。通过这个代码我深刻体会了老师所讲*&对于进行指针操作的函数的重要作用。

比如我在这个代码中定义了insertBSThelp函数进行主要迭代,那么怎么从这个函数中取出经过插入后的root指针呢?因此将此函数的入口参数设置为*&,因此这个函数就有操作外部指针的能力,经过这个函数操作的root指针再在insertIntoBST中return时就是经过插入的指针了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {

        insertBSThelp(root,val);
        return root;
    }
    void insertBSThelp(TreeNode*& root, int val){
        if(root==NULL) 
        {root= new TreeNode;
        root->val=val;
        return;
        }
        if(root->val==val) return;
        if(root->val<val) {insertBSThelp(root->right,val);}
        else { insertBSThelp(root->left,val);}
     }
};

测试例例子:

[2,1,3,null,4]
5

image-20200424213126109

测试结果

image-20200424213235564

利用search

这个例子格外加强了我对*&的理解。在我看来*&比较像对指针的操作权限,放在函数的参数上是指函数具有对参数传入指针的操作权限,而函数定义成为*&就可以让外部有权利改变函数传出的指针。

在这个例子中,依旧最终返回的应该是整个树的root,因此三个函数分别起到不同的作用。

search找到外部指针root对应的树中的对应节点的指针,传出给insertBShelp,可以看到search函数用*&的传入参数使其有权利对外部root进行修改,而函数定义*&又使得传出的位置有权利修改search内部指针,就使得search外部传出位置有权利修改外部的root的对应指针。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {

        insertBSThelp(root,val);
        return root;
    }
    void insertBSThelp(TreeNode*root, int val){
        TreeNode *&t=search(root,val);
        if(t==NULL)
            t=new TreeNode;
            t->val=val;
    }
    TreeNode*& search(TreeNode*&root,double val){
        if(root==NULL)return root;
        if(root!=NULL&&root->val==val)
            return root;
        if(root->val>val)
            return search(root->left,val);
        else return search(root->right,val);
    }
};

image-20200424215319529

删除

以删除顶端为例。

  1. 有孩子中的一个把孩子挂上去
  2. 找右子树的最左,把它的右孩挂上去。

过于混乱,不展示代码了。

堆与优先级队列

堆的作用是取前几。

堆是完全二叉树结构,因此使用数组存储。

其大小关系是局部有序的,兄弟间无关系。

  1. 插入

    只看被破坏位置到根节点路径有无被破坏,到不破坏就停

  2. 删除

    1. 顶部:把顶部和最后一个交换,顶部向下筛;比较当前三角形,如果有不是顶端的最小值就交换,等到三角形稳定就停。
    2. 中间;向上筛和向下筛都要。所以这个顺序是?
  3. 建堆

原文链接: https://www.cnblogs.com/samanthadigitalife/p/12771148.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    数据结构13—二叉搜索树,堆

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/344409

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午2:40
下一篇 2023年3月2日 上午2:41

相关推荐