二叉树的简单实现及其部分面试题

来源:互联网 发布:java list 字符串排序 编辑:程序博客网 时间:2024/06/07 02:46

树的基本概念:

    树是n(n>=0)个有限个数据的元素集合,形状像一颗倒过来的树。


    结点:结点包含数据和指向其它结点的指针。

    根节点:树第一个结点称为根节点。

    结点的度:结点拥有的子节点个数。

    叶节点:没有子节点的节点(度为0)。

    父子节点:一个节点father指向另一个节点child,则child为孩子节点,father为父亲结点。

    兄弟节点:具有相同父节点的节点互为兄弟节点。

    节点的祖先:从根节点开始到该节点所经的所有节点都可以称为该节点的祖先。

    子孙:以某节点为根的子树中任一节点都称为该节点的子孙。

    树的高度:树中距离根节点最远结点的路径长度


二叉树的概念:

    二叉树是一棵特殊的树,二叉树每个节点最多有两个孩子结点,分别称为左孩子和右孩子。

二叉树的存储方式:

    (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;

    }

    

    






本文出自 “缘去即成幻” 博客,请务必保留此出处http://liu153.blog.51cto.com/10820414/1766409

0 0
原创粉丝点击