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

Posted samanthadigitalife

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构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

技术图片

二叉搜索树的插入
递归

此递归代码和老师讲的稍微有所不同,需要返回的是整个树,也就是返回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

技术图片

测试结果

技术图片

利用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);
    }
};

技术图片

删除

以删除顶端为例。

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

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

堆与优先级队列

堆的作用是取前几。

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

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

  1. 插入

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

  2. 删除

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

以上是关于数据结构13—二叉搜索树,堆的主要内容,如果未能解决你的问题,请参考以下文章

高级数据结构---堆树和堆排序

代码题(10)— 二叉搜索树

平衡树

数据结构----二叉树(未写完)

二叉树,堆详解

【数据结构】红黑树