二叉树

来源:互联网 发布:如何当淘宝模特 编辑:程序博客网 时间:2024/06/04 17:58

二叉树:

是由N个结点组成的有限集合,该集合可为空(空二叉树),或者由一个根节点和两个互不相交的子节点组成。
二叉树的特点:
1) 最多有两棵子树,所以二叉树中不存在度大于2的结点;
2) 左子树和右子树是有序的,不可随意改变;
3) 五种基本形态:
A. 空二叉树;
B. 只有一个根节点的二叉树;
C. 根节点只有左子树;
D. 根节点只有右子树;
E. 根节点既有左子树又有右子树;
(树不能带环,子节点不能拥有多个父节点;)
特殊的二叉树:
1) 满二叉树:
在一颗二叉树中,所有的分支节点都存在左子树和右子树,并且所有的叶子都在同一层上,这样的二叉树称为满二叉树;
2) 完全二叉树:
对一棵有N个结点的二叉树按照层序编号,如果编号为i的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,这样的二叉树称为完全二叉树。(说白了其实就是将结点层序遍历存放在数组中,结点之间没有空缺。)
3) 斜树;
所有结点都在左子树的二叉树为左斜树;
所有结点都在右子树的二叉树为右斜树;
二者统称为斜树;
二叉树的表示方法:
1. 数组表示:
缺点:浪费空间,对于没有孩子的也要占用空间,只适用于完全二叉树和满二叉树;
2. 链表表示:
A. 二叉链表:有左孩子,右孩子
B. 三叉链表:有左孩子,右孩子,父节点
遍历方式:

这里写图片描述
A. 前序遍历:根结点—》左孩子—》右孩子
这里写图片描述

B. 中序遍历:左孩子—》根节点—》右孩子
这里写图片描述

C. 后序遍历:左孩子—》右孩子—》根节点
这里写图片描述

代码表示三种遍历方式:
递归遍历:

    //三种遍历方式    void printfTreePrev(Node* root)//打印tree,使用前序----根左右    {        if(root == NULL)            return;        cout<<root->_data<<" ";        printfTreePrev(root->_leftChild);        printfTreePrev(root->_rightChild);    }    void printfTreeMid(Node* root)//打印tree,使用中序----左根右    {        if(root == NULL)            return ;        printfTreeMid(root->_leftChild);        cout<<root->_data<<" ";        printfTreeMid(root->_rightChild);    }    void printfTreeBack(Node* root)//打印tree,使用后序----左右根    {        if(NULL == root)            return;        printfTreeBack(root->_leftChild);        printfTreeBack(root->_rightChild);        cout<<root->_data<<" ";    }

非递归遍历:
思想:这里以前序遍历为主我们简单分析一下:
判断当前节点(当前节点就是此时栈顶元素,此时还没有pop出来)的左子树是否有?有就pushback()当前节点的左孩子,没有就popback(),读取栈顶元素,并且访问其右子树,if右子树有,就pushback()当前节点的右孩子,然后再判断右孩子是否有左子树,有就pushback(),就这样一直循环该思想,就是下图这样的行走方式,

这里写图片描述
这里写图片描述

//采用非递归的方式---利用栈的后进先出的思想---    //先访问根节点,访问完了以后就push,然后访问左子树,直到访问的左子树为NULL,然后就pop取出栈顶元素访问其右子树,以此类推    //先序遍历----根左右    void PreOrder()    {        vector<Node*> v;        cout<<"中序遍历:"<<endl;        Node* cur = _root;        while(cur || !v.empty())        {            while(cur)            {                v.push_back(cur);                cout<<cur->_data<<" ";                cur = cur->_leftChild;            }            Node* top = v.back();            cur = top->_rightChild;            v.pop_back();        }        cout<<endl;    }    //中序遍历----左根右    void MidOrder()    {        vector<Node*> v;        cout<<"中序遍历:"<<endl;        Node* cur = _root;        while(cur || !v.empty())        {            while(cur)            {                v.push_back(cur);                cur = cur->_leftChild;            }            Node* top = v.back();            cout<<top->_data<<" ";            cur = top->_rightChild;            v.pop_back();        }        cout<<endl;    }    //后序遍历----左右根    void BackOrder()    {        vector<Node*> v;        cout<<"后序遍历:"<<endl;        Node* cur = _root;        Node* pre = NULL;        while(cur || !v.empty())        {            while(cur)            {                v.push_back(cur);                cur = cur->_leftChild;            }            Node* top = v.back();            if(top->_rightChild == NULL || top->_rightChild == pre)            {                cout<<top->_data<<" ";                pre = top;                v.pop_back();            }            else            {                cur = top->_rightChild;            }        }        cout<<endl;    }

二叉树代码补充完整:

template <class T>struct TreeNode{    T _data;    TreeNode<T>* _leftChild;    TreeNode<T>* _rightChild;    TreeNode(const T& data)        :_data(data),_leftChild(NULL),_rightChild(NULL)    {}};template <class T>class BinaryTree{    typedef TreeNode<T> Node;protected:    Node* _root;public:    BinaryTree()        :_root(NULL)    {}    BinaryTree(T* arr, size_t n, const T& invalid)    {        int a = 0;        _root = CreateTree(arr, n, invalid, a);    }    ~BinaryTree()//析构函数    {        Destory(_root);    }    //采用递归的方式    //销毁结点    void Destory(Node* root)//删除节点采用后序的遍历方式----左右根    {        if(root == NULL)            return;        Destory(root->_leftChild);        Destory(root->_rightChild);        delete root;    }    //创建一颗树    Node* CreateTree(T* arr, size_t n, const T& invalid, int& index)    {        assert(arr);        Node* root = NULL;        if(index < n && arr[index] != invalid)        {            root = new Node(arr[index]);            root->_leftChild = CreateTree(arr, n, invalid, ++index);            root->_rightChild = CreateTree(arr, n, invalid, ++index);        }        return root;    }    //计算叶子节点的个数=======左 + 右    size_t CountLeaf()    {        return _CountLeaf(_root);    }    size_t _CountLeaf(Node* root)    {        if(NULL == root)        {            return 0;        }        if(root->_leftChild == NULL && root->_rightChild == NULL)            return 1;        return _CountLeaf(root->_leftChild) + _CountLeaf(root->_rightChild);    }    //计算第K层的结点个数    size_t CountKLeaf(size_t k)    {        return _CountKLeaf(_root,k);    }    size_t _CountKLeaf(Node* root, size_t k)    {        assert(k > 0);        if(NULL == root)            return 0;        if(k == 1)            return 1;        return _CountKLeaf(root->_leftChild, k-1) + _CountKLeaf(root->_rightChild, k-1);//切勿使用--k,因为此时k是在同一层的左右子树    }    //求tree的深度-----树的高度    size_t HeightTree()    {        return _HeightTree(_root);    }    size_t _HeightTree(Node* root)    {        if(NULL == root)            return 0;        size_t left = _HeightTree(root->_leftChild) + 1;        size_t right = _HeightTree(root->_rightChild) + 1;        return left > right ? left : right;    }    //找到某个节点    void Find(const T& data)    {        Node* node = _Find(_root,data);        if(NULL == node)            cout<<"find number: NULL"<<endl;        else            cout<<"find number: "<<node->_data<<endl;    }    Node* _Find(Node* root,const T& data)    {        if(NULL == root)            return NULL;        if(root->_data == data)            return root;        Node* left = _Find(root->_leftChild,data);        if(left)            return left;        return _Find(root->_rightChild,data);       }