二叉树建立,复制,销毁及简单接口

原创 2018年01月02日 09:19:34

二叉树:节点最多只有两个子树,有左右之分,次序不可颠倒。

二叉树的建立

利用先序序列递归建立二叉树:给定一个先序遍历数组用链表创建二叉树。
建立一个二叉树节点类:

//二叉树节点的类
template<class T>
struct BinaryTreeNode
{
    //节点的构造函数
    BinaryTreeNode(const T& x)
    :_data(x)
    , _leftNode(NULL)
    , _rightNode(NULL)
    {}
    T _data;//节点数据
    BinaryTreeNode<T> *_leftNode;//左子树节点
    BinaryTreeNode<T> *_rightNode;//右子树节点
};
   当数组的元素不为 # 且数组的下标满足要求时,以数组元素数据建立头节点,左子树和右子树的建立属于子问题,用递归实现。

这里写图片描述

//二叉树类
template<class T>
class BinaryTree
{
    typedef BinaryTreeNode<T> Node;
public:

    。。。

    //利用数组建立二叉树
    //invalid用来标识 # 也就是数组中的空元素
    BinaryTree(const T* arr, size_t size, const T& invalid)
    {
        size_t index = 0;
        _root = CreatTree(arr, size, invalid, index);
    }
    Node* CreatTree(const T* arr, size_t size, const T& invalid, size_t& index) 
    //index传引用,可以有累加的功能,防止每次进函数都是从0开始
    {
        Node* root = NULL;
        //当满足if条件时,创建根节点,左子树,右子树
        if (arr[index] != invalid&&index < size)
        {
            root = new Node(arr[index]);
            root->_leftNode = CreatTree(arr, size, invalid, ++index);
            root->_rightNode = CreatTree(arr, size, invalid, ++index);  
        }
        return root;
    }

二叉树的复制

二叉树的复制包括创建新对象并用已存在的对象对其进行初始化,对已存在对象进行赋值操作。

//二叉树的复制(拷贝构造函数)
    BinaryTree(BinaryTree<T>& t)
    {
        _root = CopyTree(t._root);
    }
    Node* CopyTree(Node* root)
    {
        if (root == NULL)
        {
            return NULL;
        }
        Node* cur = new Node(root->_data);
        cur->_leftNode = CopyTree(root->_leftNode);
        cur->_rightNode = CopyTree(root->_rightNode);
        return cur;
    }
    //运算符的重载(还可以使用swap函数直接交换赋值)
    BinaryTree<T>& operator= (BinaryTree<T>& t)
    {
        if (_root)
        {
            Destory(_root);
        }
        _root = CopyTree(t._root);
        return *this;
    }

二叉树的销毁

二叉树的销毁其实就是BinaryTree类的析构函数,用递归的方法,先判断二叉树是否为空,为空直接返回;不为空的时候,转化为子问题,先销毁左子树,再右子树,后根节点。

//二叉树的销毁(析构函数)
    ~BinaryTree()
    {
        Destory(_root);
    }
    void Destory(Node* root)
    {
        //二叉树为空
        if (root == NULL)
        {
            return;
        }
        Destory(root->_leftNode);
        Destory(root->_rightNode);
        if (root)
        {
            delete root;
        }
        root = NULL;
    }

二叉树的大小

用递归的方法,将左子树节点个数和右子树节点个数相加再加上根节点。

//第一种解法:
size_t Size1()
{
    return _Size1(_root);
}
int _Size1(Node* root)
{
    if (root == NULL)
    {
        return 0;
    }
    return _Size1(root->_leftNode) + _Size1(root->_rightNode) + 1;
}

创建了局部变量count用来对节点个数进行记录,只要每次传进函数的节点不为空,count都会进行累加操作, 切记参数传递的时候一定是引用,防止每次进函数时其值是0。

//第二种解法:
size_t Size2()
{
    size_t count = 0;
    return _Size2(_root,count);
}
int _Size2(Node* root,size_t& count)
{
    if (root == NULL)
    {
        return 0;
    }
    count++;
    _Size2(root->_leftNode,count);
    _Size2(root->_rightNode,count);
    return count;
}

二叉树的深度

二叉树的深度是指二叉树所有路径中最长的路径。
运用递归的方法,比较根节点左子树,右子树路径的长度,再对左子树,右子树进行单独处理;根节点的左子树节点会分为左子树,右子树;根节点的右子树节点也会分为左子树,右子树……不断的进行。当整棵树的节点被计算完选择最长的路径再加上根节点就是二叉树的深度。

size_t Depth()
{
    return _Depth(_root);
}
size_t _Depth(Node* root)
{
    if (root == NULL)
    {
        return 0;
    }
    size_t leftD = _Depth(root->_leftNode);
    size_t rightD = _Depth(root->_rightNode);
    return leftD > rightD ? leftD + 1 : rightD + 1;
}

二叉树的叶子节点

二叉树的叶子节点是指一个节点既没有左子树节点也没有右子树节点。
判断的条件:左子树节点为NULL,右子树节点为NULL。满足条件对其调用者返回1,然后调用者对返回的个数进行累加。

//第一种解法
size_t LeafSize1()
{
    return _LeafSize1(_root);
}
int _LeafSize1(Node* root)
{
    if (root == NULL)
    {
        return 0;
    }
    if (root->_leftNode == NULL&&root->_rightNode == NULL)
    {
        return 1;
    }
    return _LeafSize1(root->_leftNode) +_LeafSize1(root->_rightNode);
}

每找到一个满足条件的节点就对count进行++,再对根节点的左子树节点,右子树节点进行判断,直至整棵树的节点被访问。

//第二种解法
size_t LeafSize2()
{
    size_t count = 0;
    return _LeafSize2(_root, count);
}
size_t _LeafSize2(Node* root,size_t& count)
{
    if (root == NULL)
    {
        return 0;
    }
    if (root->_leftNode == NULL&&root->_rightNode == NULL)
    {
        ++count;
    }
    _LeafSize2(root->_leftNode,count);
    _LeafSize2(root->_rightNode,count);
    return count;
}

二叉树第K层节点

size_t GetKLevel(size_t k)
{
    return _GetKLevel(_root,k);
}
int _GetKLevel(Node* root,size_t k)
{
    //数为空时返回0
    if (root == NULL)
    {
        return 0;
    }
    //当是第一层节点时,只有根节点返回1
    if (k == 1)
    {
        return 1;
    }
    //当K大于1时,返回左子树第K-1层节点数加右子树第K-1层节点数
    return _GetKLevel(root->_leftNode, k-1) + _GetKLevel(root->_rightNode, k-1);
}

二叉树的查找

在二叉树中查找一个指定的数

  • 二叉树为空的时候,返回NULL;
  • 不为空时,对二叉树的左子树节点和右子树节点分别进行判断,找到的话返回节点。
Node* FindNode(const T& x)
{
    return _FindNode(_root,x);
}
Node* _FindNode(Node* root, const T& x)
{
    if (root == NULL)
    {
        return NULL;
    }
    if (root->_data == x)
    {
        return root;
    }
    Node* ret = _FindNode(root->_leftNode, x);
    if (ret)
    {
        return ret;
    }
    else
    {
        return NULL;
    }
    Node* cur = _FindNode(root->_rightNode, x);
    if (cur)
    {
        return cur;
    }
    else
    {
        return NULL;
    }
}

注:运用递归算法时,被调函数的参数在本函数中就是根节点,不再是左子树节点或右子树节点,这个问题需注意。

版权声明:本文为博主原创文章,未经博主允许不得转载。

二叉树的创建、销毁、各种递归、循环遍历方法(可运行测试)

因为二叉树的定义就是递归的, 所以二叉树、创建、销毁和各种遍历操作都使用递归的方法,会比较好理解。递归其实主要运用到了系统工作栈, 因此可以使用递归实现的,借助用户栈一般也可以实现, 本文中三种遍历方...
  • haoyuedangkong_fei
  • haoyuedangkong_fei
  • 2016年05月25日 14:47
  • 1126

【二叉树】二叉树的创建、遍历、销毁、求树的最大深度

建立二叉树的链式存储结构,并对二叉树前序遍历、中序遍历、后序遍历以及层序遍历,求二叉树的深度,销毁二叉树。 (1)二叉树的建立 前序建立,即先建立根节点,再建立左子树,最后建立右子树,结点值的输入...
  • yebanxin
  • yebanxin
  • 2016年08月06日 22:29
  • 1703

二叉排序树的创建(结点的插入,删除等操作)

二叉排序树的理论看课本 代码如下: BSTree.h struct BSTreeNode; typedef struct BSTreeNode *ptrtreenode; void Make...
  • jw903
  • jw903
  • 2014年05月05日 22:49
  • 1272

二叉树的简单接口

二叉树的简单操作
  • Li_Ning_
  • Li_Ning_
  • 2016年03月30日 14:02
  • 243

数据结构二叉树接口实现

  • 2017年01月01日 23:32
  • 1.49MB
  • 下载

二叉树的建立与遍历(C语言简单实现)

#include #include #include #define MAXSIZE 1024//二叉树节点 typedef struct tNode{ char data; tN...
  • relaying
  • relaying
  • 2015年10月25日 20:49
  • 318

简单中序算术表达式直接建立二叉树测试

/* 简单中序算术表达式转为二叉树, 至于转成了二叉树, 前中后遍历就随意了 1. 将表达式转为后缀表达式, 然后转为二叉树, 或者用2步骤. 2. 理论上来讲, 一个中缀表达式是不能够转...
  • u014440013
  • u014440013
  • 2014年11月11日 23:08
  • 1265

平衡二叉树的简单建立--示例

PG.lua文件 -- 这个用来输出处理 打logPG = {} function PG.Log(str) print(str); end 首先是pinghengtree.lua文件...
  • yangjie6898862
  • yangjie6898862
  • 2016年07月10日 22:16
  • 315

二叉树的简单实现

  • 2013年12月09日 15:21
  • 5KB
  • 下载

二叉树的C++简单实现

  • 2013年12月09日 14:39
  • 4KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉树建立,复制,销毁及简单接口
举报原因:
原因补充:

(最多只允许输入30个字)