二叉樹的簡單實現及其部分面試題

樹的基本概念:ios

    樹是n(n>=0)個有限個數據的元素集合,形狀像一顆倒過來的樹。數組


    結點:結點包含數據和指向其它結點的指針。ide

    根節點:樹第一個結點稱爲根節點。函數

    結點的度:結點擁有的子節點個數。this

    葉節點:沒有子節點的節點(度爲0)。spa

    父子節點:一個節點father指向另外一個節點child,則child爲孩子節點,father爲父親結點。3d

    兄弟節點:具有相同父節點的節點互爲兄弟節點。指針

    節點的祖先:從根節點開始到該節點所經的全部節點均可以稱爲該節點的祖先。orm

    子孫:以某節點爲根的子樹中任一節點都稱爲該節點的子孫。blog

    樹的高度:樹中距離根節點最遠結點的路徑長度


二叉樹的概念:

    二叉樹是一棵特殊的樹,二叉樹每一個節點最多有兩個孩子結點,分別稱爲左孩子和右孩子。

二叉樹的存儲方式:

    (1)數組存儲方式  即用一組連續的存儲單元存儲二叉樹的數據元素。

    例如:

wKiom1cYw3GCxDqdAACF3eqTWVU541.png

    (2)鏈式存儲方式

wKiom1cYxYiSRTJyAACS0KFS2kk419.png

    這裏咱們主要討論每一個結點包含三個域的狀況

    二叉樹的結點的結構

    template<class T>

    struct BinaryTreeNode

    {

     BinaryTreeNode(const T& x)  //構造函數

     :_data(x)

     ,_left(NULL)

     ,_right(NULL)

     { }

    

     T _data;  //結點的值

     BinaryTreeNode<T>* _left;  //指向左子樹的結點

     BinaryTreeNode<T>* _right; //指向右子樹的結點

    };

    

    部分代碼以下:

    二叉樹的遍歷(前序、中序、後序、層次)

    void _PrevOrder(Node* root) //前序遍歷打印二叉樹

    {

if(root == NULL)

    return ;

cout<<root->_data<<" ";

_PrevOrder(root->_left);

_PrevOrder(root->_right);

    }


    void _InOrder(Node* root) //中序遍歷打印二叉樹

    {

if(root == NULL)

            return;

_InOrder(root->_left);

cout<<root->_data<<" ";

_InOrder(root->_right);

    }


    void _PosOrder(Node* root) //後序遍歷打印二叉樹

    {

if(root == NULL)

    return;

_PosOrder(root->_left);

_PosOrder(root->_right);

cout<<root->_data<<" ";

    }


    void _LevelOrder(Node* root) //層次遍歷

    {

queue<Node*> p;

if(root == NULL)

{

    return;

}

p.push(root);

while (!p.empty())

{

    if(p.front()->_left != NULL)

         {

p.push(p.front()->_left);

            }

    if(p.front()->_right != NULL)

    {

p.push(p.front()->_right);

    }

    cout<<p.front()->_data<<" ";

    p.pop();

}

    }

    二叉樹中結點的個數

    size_t _Size(Node* root) //求結點的個數

    {

if(root == NULL)

    return 0;

return _Size(root->_left) + _Size(root->_right) + 1;

    }

    二叉樹的深度

    size_t _Depth(Node* root) //樹的深度

    {

if(root == NULL)

    return 0;

size_t leftdepth = _Depth(root->_left);

size_t rightdepth = _Depth(root->_right);

return leftdepth > rightdepth ? leftdepth + 1 : rightdepth + 1;

    }

    二叉樹葉子節點的個數

    size_t _LeafSize(Node* root) // 葉子節點的個數

    {

if(root == NULL)

    return 0;

if(root->_left == NULL && root->_right == NULL)

    return 1;

return _LeafSize(root->_left) + _LeafSize(root->_right);

    }

    二叉樹的鏡像(即交換二叉樹每個結點的左右子結點)

    void _MirrorRecursively(Node* root)//二叉樹的鏡像

    {

//判斷根節點及左右子樹是否爲空

if(root == NULL || (root->_left == NULL && root->_right == NULL))

    return;

Node* temp = root->_left;  //交換左右子節點

root->_left = root->_right;

root->_right = temp;

if(root->_left != NULL)

    _MirrorRecursively(root->_left);

if(root->_right != NULL)

    _MirrorRecursively(root->_right);

    }

    判斷子樹問題

    bool HasSubtree(Node* root2)//判斷root2是不是_root的子樹

    {

bool result = false;

if(_root != NULL && root2 != NULL)

{

    if(_root->_data == root2->_data)

    {

result = DoseTree1HaveTree2(_root,root2);

    }

    if(!result)

                result = HasSubtree(_root->_left,root2);

    if(!result)

result = HasSubtree(_root->_right,root2);

        }

        return result;

    }

    bool DoseTree1HaveTree2(Node* root2)//判斷在tree1中是否有以tree2根節點的左右子樹結構

    {

if(root2 == NULL)

    return true;

if(_root == NULL)

    return false;

if(_root->_data != root2->_data)

    return false;

return DoseTree1HaveTree2(_root->_left,root2->_left) && DoseTree1HaveTree2(_root->_right,root2->_right);

    }

    以上只是部分代碼,具體源代碼以下:

    

    #pragma once 

    #include<iostream>

    #include<queue>

    using namespace std;


    //二叉樹中結點的結構

    template<class T>

    struct BinaryTreeNode

    {

     BinaryTreeNode(const T& x)  //構造函數

     :_data(x)

     ,_left(NULL)

     ,_right(NULL)

     { }  

     T _data;  //結點的值

     BinaryTreeNode<T>* _left;  //指向左子樹的結點

     BinaryTreeNode<T>* _right; //指向右子樹的結點

    };


    template<class T>

    class BinaryTree

    {

     typedef BinaryTreeNode<T> Node;//簡化命名

    public:

     BinaryTree() //默認構造函數

     :_root(NULL)

     { }

    

     BinaryTree(const T* a,size_t size,const T& invalid) //構造函數

     :_root(NULL)

     {

     size_t index = 0;

     _root = _CreateTree(a,size,invalid,index); //建立一個二叉樹

     }

    

     BinaryTree(const BinaryTree<T>& t) //拷貝構造函數

     :_root(NULL)

     {

     _Copy(t._root);

     }

    

     BinaryTree<T>& operator=(const BinaryTree<T>& t) //賦值函數

     {

     if(this != &t)

     {

     _Destroy(t._root);

     _Copy(t._root);

     }

     return *this;

     }

    

     ~BinaryTree() //析構函數

     {

     if(_root)

     {

     _Destroy(_root);

     }

     }

    

     void PrevOrder() //前序遍歷打印二叉樹

     {

     cout<<"前序遍歷:";

     _PrevOrder(_root);

     cout<<endl;

     }

    

     void InOrder()//中序遍歷打印二叉樹

     {

     cout<<"中序遍歷:";

     _InOrder(_root);

     cout<<endl;

     }

    

     void PosOrder()//後續序遍歷打印二叉樹

     {

     cout<<"後序遍歷:";

     _PosOrder(_root);

     cout<<endl;

     }

    

     void LevelOrder() //層次遍歷

     {

     cout<<"層次遍歷:";

     _LevelOrder(_root);

     cout<<endl;

     }

    

     size_t Size() //求結點的個數

     {

     return _Size(_root);

     }

    

     size_t Depth()//樹的深度

     {

     return _Depth(_root);

     }

    

     size_t LeafSize() //葉子節點個數 

     {

     return _LeafSize(_root);

     }

    

     bool HasSubtree(Node* root2)//判斷root2是不是_root的子樹

     {

     bool result = false;

     if(_root != NULL && root2 != NULL)

     {

     if(_root->_data == root2->_data)

     {

     result = DoseTree1HaveTree2(_root,root2);

     }

     if(!result)

     result = HasSubtree(_root->_left,root2);

     if(!result)

     result = HasSubtree(_root->_right,root2);

     }

     return result;

     }

    

     void MirrorRecursively()//二叉樹的鏡像

     {

     _MirrorRecursively(_root);

     }

    

    

    protected:

     Node* _CreateTree(const T* a,size_t size,const T& invalid,size_t& index) //建立一個二叉樹

     {

     Node* root = NULL;

     if(a[index] != invalid && index < size)

     {

     root = new Node(a[index]);

     root->_left = _CreateTree(a,size,invalid,++index);

     root->_right = _CreateTree(a,size,invalid,++index);

     }

     return root;

     }

    

     void _Copy(Node* sroot)//拷貝函數

     {

     Node* root = NULL;

     if(sroot == nul) //判斷根節點

     return;

     if(sroot->_left && sroot->_right) //判斷根節點的左右子樹

     {

     root = new Node(sroot->_data);

     return ;

     }

     root->_left = _Copy(sroot->_left);//依次拷貝左子樹

     root->_right = _Copy(sroot->_right);//依次拷貝右子樹

     }

    

     void _Destroy(Node* root)//銷燬二叉樹

     {

     if(root == NULL)

     {

     return;

     }

     if(root->_left && root->_right)

     {

     delete root;

     root = NULL;

     return;

     }

     _Destroy(root->_left);

     _Destroy(root->_right);

     }

    

     void _PrevOrder(Node* root) //前序遍歷打印二叉樹

     {

     if(root == NULL)

     return ;

     cout<<root->_data<<" ";

     _PrevOrder(root->_left);

     _PrevOrder(root->_right);

     }

    

     void _InOrder(Node* root) //中序遍歷打印二叉樹

     {

     if(root == NULL)

     return;

     _InOrder(root->_left);

     cout<<root->_data<<" ";

     _InOrder(root->_right);

     }

    

     void _PosOrder(Node* root) //後序遍歷打印二叉樹

     {

     if(root == NULL)

     return;

     _PosOrder(root->_left);

     _PosOrder(root->_right);

     cout<<root->_data<<" ";

     }

    

     void _LevelOrder(Node* root) //層次遍歷

     {

     queue<Node*> p;

     if(root == NULL)

     {

     return;

     }

     p.push(root);

     while (!p.empty())

     {

     if(p.front()->_left != NULL)

     {

     p.push(p.front()->_left);

     }

     if(p.front()->_right != NULL)

     {

     p.push(p.front()->_right);

     }

     cout<<p.front()->_data<<" ";

     p.pop();

     }

     }

    

     void _MirrorRecursively(Node* root)//二叉樹的鏡像

     {

     //判斷根節點及左右子樹是否爲空

     if(root == NULL || (root->_left == NULL && root->_right == NULL))

     return;

     Node* temp = root->_left;  //交換左右子節點

     root->_left = root->_right;

     root->_right = temp;

     if(root->_left != NULL)

     _MirrorRecursively(root->_left);

     if(root->_right != NULL)

     _MirrorRecursively(root->_right);

     }

    

     size_t _Size(Node* root) //求結點的個數

     {

     if(root == NULL)

     return 0;

     return _Size(root->_left) + _Size(root->_right) + 1;

     }

    

     size_t _Depth(Node* root) //樹的深度

     {

     if(root == NULL)

     return 0;

     size_t leftdepth = _Depth(root->_left);

     size_t rightdepth = _Depth(root->_right);

     return leftdepth > rightdepth ? leftdepth + 1 : rightdepth + 1;

     }

    

     size_t _LeafSize(Node* root) // 葉子節點的個數

     {

     if(root == NULL)

     return 0;

     if(root->_left == NULL && root->_right == NULL)

     return 1;

     return _LeafSize(root->_left) + _LeafSize(root->_right);

     }

    

     bool DoseTree1HaveTree2(Node* root2)//判斷在tree1中是否有以tree2根節點的左右子樹結構

     {

     if(root2 == NULL)

     return true;

     if(_root == NULL)

     return false;

     if(_root->_data != root2->_data)

     return false;

     return DoseTree1HaveTree2(_root->_left,root2->_left) && DoseTree1HaveTree2(_root->_right,root2->_right);

     }

    

    protected:

     Node* _root;//根節點

    };

    

    void Test()

    {

     int a1[10] = {1,2,3,'#','#',4,'#','#',5,6};

     int a2[15] = {1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8,};

     int a3[5] = {2,3,'#','#',4};

    

     BinaryTree<int> t1(a1,10,'#');

     BinaryTree<int> t2(a2,15,'#');

     BinaryTree<int> t3(a3,5,'#');

    

     cout<<"t1遍歷二叉樹(前序,中序,後序,層次):"<<endl;

     t1.PrevOrder();

     t1.InOrder();

     t1.PosOrder();

     t1.LevelOrder();

     cout<<"二叉樹結點的個數:"<<t1.Size()<<endl;

     cout<<"二叉樹的深度:"<<t1.Depth()<<endl;

     cout<<"二叉樹的葉子節點數:"<<t1.LeafSize()<<endl;

     cout<<"二叉樹的鏡像:"<<endl;

     t1.MirrorRecursively();

     t1.PrevOrder();

     cout<<endl;

    

     cout<<"t2遍歷二叉樹(前序,中序,後序,層次):"<<endl;

     t2.PrevOrder();

     t2.InOrder();

     t2.PosOrder();

     t2.LevelOrder();

     cout<<"二叉樹結點的個數:"<<t2.Size()<<endl;

     cout<<"二叉樹的深度:"<<t2.Depth()<<endl;

     cout<<"二叉樹的葉子節點數:"<<t2.LeafSize()<<endl;

     cout<<"二叉樹的鏡像:"<<endl;

     t2.MirrorRecursively();

     t2.PrevOrder();

     cout<<endl;

    }

相關文章
相關標籤/搜索