二叉树的前序、中序、后序、层序遍历的递归及非递归,

二叉树的基本概念
每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。
性质:
1、非空二叉树的第n层上至多有2^(n-1)个元素。
2、深度为h的二叉树至多有2^h-1个结点。
3、满二叉树:所有终端都在同一层次,且非终端结点的度数为2。
4、在满二叉树中若其深度为h,则其所包含的结点数必为2^h-1。
5、完全二叉树:除了最大的层次即成为一颗满二叉树且层次最大那层所有的 结点均向左靠齐,即集中在左面的位置上,不能有空位置。
对于完全二叉树,设一个结点为i则其父节点为i/2,2i为左子节点,2i+1为右子节点。
实现语言:C++

树的结构:将数据存储在数组中,虽然访问速度比较块,但占的内存空间比较大,因此通常采用链式存储结构

typedef int datatype;
typedef struct BTNode
{
    datatype val;
    BTNode *left;
    BTNode *right;
}BTNode;

前序遍历

根节点->左子树->右子树
前序递归遍历:用递归的方法先根节点,再左子树,最后右子树依次遍历即可

void Prevorder(Node* root)
{
    if (root)
    {
        cout << root->data;
        Prevorder(root->left);
        Prevorder(root->right);
    }
}

前序非递归遍历:前序遍历的思想是借助栈来实现的,先遍历不为空的节点,然后依次将不为空的节点依次入栈,当最后一个节点的左子树为空时,取出最后一个节点,然后将这个节点删除,访问取出节点的右子树。当栈和当前节点都为空时,说明遍历完毕。(非递归转递归的思想就是变递归为循环

void PrevOrder_NonR()
    { 
        Node* cur = _root;
        stack<Node*> s;
        while (cur || !s.empty())
        {
            while (cur)
            {
                cout << cur->_data << "->";
                s.push(cur);
                cur = cur->_left; 
            }
            Node*top= s.top();
            s.pop();
            cur = top->_right;
            }
        }

中序遍历

左子树->根节点->右子树
中序递归遍历:当树不为空时,才进行遍历,依次遍历树的左子树,根节点,右子树

void _InOrder(Node* _root)
    {
        if (_root)
        {
            _InOrder(_root->_left);
            cout << _root->_data << "->";
            _InOrder(_root->_right);
        }
    }

中序遍历非递归遍历:借助栈来实现中序遍历的非递归,如果当前节点不为空时,就依次循环遍历。找到整棵树的最左节点,然后遍历这颗树的最左节点,遍历完之后就删除当前节点,由于不确定当前节点是否还有右子树,所以访问当前节点之前,需要事先保存当前节点,如果当前节点和栈都为空时,遍历完成。

void InOrder_NonR()//中序遍历
    {
        Node* cur = _root;
        stack<Node*> s;//在这里要定义成一个结构体 若定义成一个整型无法访问下一个节点  以便可以找到下一个节点
        while (cur || !s.empty())
        {
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }
            Node* top = s.top();
            cout << top->_data << "->";
            s.pop();
            cur = top->_right;
         }
    }

后续遍历

左子树->右子树->根节点
后序递归遍历:当树不为空时,才进行遍历,依次遍历树的左子树,右子树,根节点

void _EndOrder(Node* _root)
    {
        if (_root)
        {

            _EndOrder(_root->_left);
            _EndOrder(_root->_right);
            cout << _root->_data << "->";
        }
    }

后续非递归遍历:后续遍历的非递归相对有一点难度,需要设置一个

void EndOrder_NonR()//后续遍历,需要定义一个指向前一个节点的指针
    {
        Node* cur = _root;
        stack<Node*> s;
        Node* prev = NULL;
        while (cur || !s.empty())
        {
            while (cur)
            {
                s.push(cur);
                cur = cur->_left;
            }
            Node* top = s.top();
            if (((top->_right) == NULL) ||( top->_right == prev))
            {
                cout << top->_data<<"->";
                s.pop();
                prev=top;
            }
            else
                cur = top->_right;
        }

    }

二叉树的层序遍历

二叉树的层序遍历借助一个队列来实现,如果树不为空,就将树的根节点入队列,每次出一个根节点,就将这个节点的左右子树分别入队列,当没有数据要入队列时,就将队列中的所有队列打印处出来。

void _SeqOrder(Node* _root)//层序遍历  层序遍历是以队列的思想来实现的(画图)
    {
        queue<Node*> q;
        if (_root)
        {
            q.push(_root);
         }
        while (!q.empty())//当队列不为空时,进入循环打印
        {
            Node* tmp = q.front();
            cout << tmp->_data<<"->";
            q.pop();
            if (tmp->_left)
            {
                q.push(tmp->_left);
            }
            if (tmp -> _right)
            {
                q.push(tmp->_right);
            }

        }

    }

猜你喜欢

转载自blog.csdn.net/wyn126/article/details/81436809
今日推荐