数据结构——二叉树

来源:互联网 发布:网页编程入门 编辑:程序博客网 时间:2024/05/21 01:30

二叉树是数据结构的一个重要内容之一,那么对于我们这些学习编程的人来说,掌握二叉树的各种遍历(递归遍历和非递归遍历)是必不可少的,下面我们就分析一下,二叉树的各种遍历方法:

1首先得建立一个二叉树:

1.二叉树节点
struct BinaryTreeNode//二叉树节点 {     BinaryTreeNode* _left;     BinaryTreeNode* _right;     T _data;     BinaryTreeNode(const T data)        :_left(NULL)//二叉树左孩子        ,_right(NULL)//右孩子        ,_data(data)    {    }}; 
2.造二叉树
BinaryTree(const T* a, size_t size, const T& invalid)//二叉树构造函数            :_root(NULL)        {            size_t index=0;            _root=CreatBinaryTree(a,size,index,invalid);        }
Node* CreatBinaryTree(const T* a,size_t size,size_t& index,const T& invalid)//制造二叉树(前序)    {        Node* root=NULL;        if(a[index]!=invalid&&index<size)        {            root=new Node(a[index]);//new一个根节点,先造根节点            root->_left=CreatBinaryTree(a,size,++index,invalid);//再造左节点            root->_right=CreatBinaryTree(a,size,++index,invalid);//再造右节点        }        return root;    }   
3.遍历二叉树(递归)
①前序遍历,前序遍历是1.遍历根节点、2.遍历左节点、3.遍历有节点
void PrevOrder()//前序遍历    {        _PrevOrder(_root);//传根节点        cout<<endl;    }    void _PrevOrder(Node* T)    {        if(T==NULL)            return;        else        {            cout<<T->_data<<" ";//先访问根节点,在这里是直接输出            _PrevOrder(T->_left);//访问左节点            _PrevOrder(T->_right);//访问有节点        }    }
②中序遍历(递归),中序遍历和前序遍历类似,只不过是将访问顺序变为1.左节点、2.根节点、3.有节点
void InOrder()    {        _InOrder(_root);        cout<<endl;    }    void _InOrder(Node* T)    {        if(T==NULL)            return;        else        {            _InOrder(T->_left);            cout<<T->_data<<" ";            _InOrder(T->_right);        }    }    void PostOrder()    {        _PostOrder(_root);        cout<<endl;    }
③后序遍历,也不例外,1.访问左节点、2.访问右节点、3.访问根节点
void PostOrder()    {        _PostOrder(_root);        cout<<endl;    }void _PostOrder(Node* T)    {        if(T==NULL)            return;        else        {            _PostOrder(T->_left);//访问左节点            _PostOrder(T->_right);//访问右节点            cout<<T->_data<<" ";//访问根节点        }    }
4.非递归遍历二叉树
①前序序访问二叉树

这里写图片描述

前序采用栈来处理,如图所示,先压1,然后出1,压 2,3,这里先压3,后压2,是栈的特点,后进先出所以先出2,压 5、 4;然后出4,压9、 8;出 8,然后出9、出 5、出3;压 7 、6,出7,出6;

得到1,2,4,8,9,5,3,7,6;

void PrevOrder_NonR()    {        Node* T = _root;        stack<Node*> s;        while(T!=NULL||!s.empty())        {            if(T!=NULL)            {                cout<<T->_data<<" ";                s.push(T);                T=T->_left;            }            else            {   T=s.top();                s.pop();                T=T->_right;            }        }        cout<<endl;    }
②中序遍历
中序遍历和前序是一样的采用栈来处理,只不过是先访问左节点,然后根节点、右节点
void InOrder_NonR()    {        Node* T = _root;        stack<Node*> s;        if(T==NULL)            return;        else        {            Node* temp=T;            while(!s.empty()||temp!=NULL)               {                if(temp!=NULL)                {                    s.push(temp);//先将所有的走节点压进去                    temp=temp->_left;                }                else                {                    temp=s.top();//访问节点                    cout<<temp->_data<<" ";//记录                    s.pop();//出栈                    temp=temp->_right;//判断有节点;                }            }            cout<<endl;        }    }
③后序访问
后序访问就比较复杂了,我解决他的办法是采用俩个栈,首先要说明的是:后序和前序是有关系的,来对比一下,前序:1.根节点、2.左节点、3.右节点后续:1.左节点、2、右节点、3.根节点。那么我们可以采用类似的方法:处理先以1.根节点、2.右节点、3.左节点 这种方式遍历并将遍历结果压入output栈中,然后出栈退栈,既得到1.左节点、2.右节点、3.根节点。
void PostOrder_NonR()    {        Node* T = _root;        stack<Node*> s,output;        while(T!=NULL||!s.empty())        {            if(T!=NULL)            {                s.push(T);//先根节点                output.push(T);//入栈                T=T->_right;//右节点            }            else            {                   T=s.top();                s.pop();                T=T->_left;//走左节点            }        }        while(output.size()!=0)        {            Node* temp = output.top();            cout<<temp->_data<<" ";            output.pop();        }        cout<<endl;    }
④层序访问二叉树
#下图是层序访问的结构图

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

有上述结构图可以看出这种访问方式,与队列是一模一样的,所以我们采用队列的方式解决。1.现将1入队,先记录1 然后出队(访问),通过1来使得2、3入队;然后2,记录后2出队,4 、5入队;然后3,记录后出队,6 、7入队….,就这样一直走下去直到队列为空为止。
void LevelOrder()    {        Node* root = _root;        queue<Node*> q;        if(root)            q.push(root);//先使得第一个节点入队        while(q.size()!=0)        {            Node* temp=q.front();//记录            q.pop();//出队            cout<<temp->_data<<" ";            if(temp->_left!=NULL)//先左                q.push(temp->_left);            if(temp->_right!=NULL)//后右                q.push(temp->_right);        }        cout<<endl;    }