• 二叉树存储及遍历


    1、树的存储:

    注意:树的深度是从根节点开始(其深度为1)自顶向下逐层累加的,而高度是从叶节点开始(其高度为1)自底向上逐层累加的。虽然树的深度和高度一样,但是具体到树的某个节点,其深度和高度是不一样的。我的理解是:非根非叶结点的深度是从根节点数到它的,高度是从叶节点数到它的。

    二叉树的存储:1、数组存储(此方法适合完全二叉树的存储)

                       2、链表存储(可分为二叉链表,三叉链表)结构如下:

    2、 使用二叉链表实现二叉树

     测试用例:

    int a[10] = { 1, 2, '#', '#', 3, 4, '#', '#', 5, 6 };//其中用'表示空'

    按前序遍历的算法重建出二叉树为:(先创建根节点,再创建左子树,后创建右子树)

                                                

    代码实现:

    BinaryTree<T>* _CreateBinaryTree(const T *a,size_t size, size_t&index)
        {
            assert(a);
            BinaryTreeNode<T> *node = new BinaryTreeNode<T> (a[index]);
            if (index < size&&a[index++] != '#')
            {
                node->_left = _CreateBinaryTree(a, size, ++index);
               node->_right = _CreateBinaryTree(a, size, ++index);
    
            }
            else
    {
    return NULL;
    }
    return node; }

     3、二叉树的遍历

    以上图的二叉树为例:

    1-a、先序遍历(由于二叉树的结构具有递归的特性可以采用递归的方式遍历)

    void _PrevOrder(BinaryTreeNode<T>* root)
        {
            if (root)
            {
                cout<<root->_data<<" ";
                _PrevOrder(root->_left);
                _PrevOrder(root->_right);
            }
            else
                 return;
            
        }

    1-b、二叉树的非递归先序遍历
    思想:1、可以采用栈先进先出的原则:先使根节点入栈,栈不为空打印栈顶元素,弹出栈顶元素,

             2、在使栈顶元素的不为空右子树入栈,再使栈顶元素的不为空左子树入栈

             3、 再按1、2进行判断直至栈为空退出

    void PrevOrder_NonR(BinaryTreeNode<T> *_root)
        {
            if (_root==NULL)
            {
                return;
            }
            stack<BinaryTreeNode<T>*> s1;
            s1.push(_root);
            while (!s1.empty())
            {
                BinaryTreeNode<T> *top=s1.top();
                cout<<top->_data<<" ";
                s1.pop();
                if (top->_right)
                {
                    s1.push(top->_right);
                }
                if (top->_left)
                {
                    s1.push(top->_left);
                }
            }
            cout<<endl;
        }

    2-a、二叉树的中序遍历(递归)

    void _InOrder(BinaryTreeNode<T>* root)
        {
            if (root)
            {
                _InOrder(root->_left);
                cout<<root->_data<<" ";
                _InOrder(root->_right);
            }
            else
            {
                return;
            }
        }

    2-b、二叉树的中序遍历非递归

    思想:中序遍历是先遍历左子树,再遍历根节点,后遍历右子树

            1、使cur指向根节点,使cur->_left入栈直至cur为空(定义cur是为了指向当前遍历的节点)

            2、若栈不为空,打印栈顶元素,使cur指向栈顶元素的右子树(当前的栈顶元素也就是某一个树的根节点,但其右子树还未遍历所以使cur指向其右子树)

            3-a、若栈不为空,前一步栈顶元素的右子树为空,直接打印当前栈顶元素也就是前一步栈顶元素的根节点

            3-b、若栈不为空,前一步栈顶元素的右子树不为空,使cur指向的右子树入栈

            4、在按照2,3的步骤循环,直至cur和栈为空时结束

    //非递归中序
        void InOrder_NonR(BinaryTreeNode<T> *root)
        {
            stack<BinaryTreeNode<T>*> s1;
            BinaryTreeNode<T>* cur=_root;
            while (cur||!s1.empty())
            {
                while (cur)
                {
                    s1.push(cur);
                    cur=cur->_left;
                }
                if (!s1.empty())
                {
                    BinaryTreeNode<T>* top=s1.top();
                    cout<<top->_data<<" ";
                    s1.pop();
                    cur=top->_right;
                }
    
            }
            cout<<endl;
        }

    3-a二叉树的后续遍历(递归)

    void _PostOrder(BinaryTreeNode<T>* root)
        {
            if (root)
            {
                _PostOrder(root->_left);
                _PostOrder(root->_right);
                cout<<root->_data<<" ";
            }
            else
            {
                return;
            }
        }
  • 相关阅读:
    扩展的friend语法
    常量表达式
    字符串过滤,排序输出数字的问题
    decltype类型声明- 现代C++新特性总结
    auto类型-现代C++新特性
    指针相关总结2
    指针相关总结1
    发现XMind一个超级牛逼的功能
    空类指针为什么可以调用类的成员函数 以及 A(){}和A();
    SSAS父子层次结构的增强-UnaryOperatorColumn属性
  • 原文地址:https://www.cnblogs.com/Blog-day/p/My_Blog_Days-13.html
Copyright © 2020-2023  润新知