數據結構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. 建堆


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM