树的遍历:就是按某种特定次序不遗漏、不重复地访问树的每个节点的过程。访问次序有很多种,主要有中序遍历、前序遍历、后序遍历、深度优先遍历和广度优先遍历几种方式。中序遍历:先访问当前节点的左子树,然后访问当前节点,最后访问当前节点的右子树。后序遍历:先访问当前节点的左子树,再访问当前节点的右子树,最后访问当前节点。前序遍历:先访问当前节点,然后访问当前节点的左子树,最后访问当前节点的右子树。对于二叉树而言,深度优先遍历和先序遍历是相同的。广度优先遍历:首先访问根节点,然后由左至右访问根节点的孩子节点,再由左至右访问跟节点的孙子节点,依次类推。
1)先序遍历
递归方式实现:按照“根节点-左孩子-右孩子”顺序遍历,代码如下:
void preorder(TreeNode *root) //前序递归实现 { if (root==NULL) { return; } cout<<root->val<<"\t"; preorder(root->left); preorder(root->right); }非递归方式实现:利用栈的特性来实现。实现过程:对于任一节点P,如果P不为空,将P压入栈中。取出栈顶元素赋值给P,输出P节点对应的值。如果P的右孩子节点不为空,则将右孩子节点压入栈;如果P的左孩子节点不为空,则将左孩子节点压入栈。如此循环,直至栈中元素为空。代码如下:
void preorder_stack(TreeNode *root) //前序非递归实现 { if (root==NULL) { return; } stack<TreeNode *> nodes; TreeNode *temp; nodes.push(root); while(!nodes.empty()) { temp=nodes.top(); nodes.pop(); cout<<temp->val<<"\t"; if(temp->right!=NULL) { nodes.push(temp->right); } if(temp->left!=NULL) { nodes.push(temp->left); } } }2)中序遍历
void inorder(TreeNode *root) //中序递归实现 { if (root==NULL) { return; } inorder(root->left); cout<<root->val<<"\t"; inorder(root->right); }非递归实现:利用栈的特性来实现。实现过程:对于任一节点P,若其左孩子不为空,则将P压入栈并把P的左孩子置为P,然后对当前节点P再进行相同的处理。若其左孩子不为空,则取栈顶元素并进行出栈操作,然后将P置为栈顶元素的右孩子节点。如此循环,直至P为NULL且栈为空为止。代码如下:
void inorder_stack(TreeNode *root) //中序非递归实现 { if (root==NULL) { return; } stack<TreeNode *> nodes; TreeNode *temp=root; while(temp!=NULL || !nodes.empty()) { while(temp!=NULL) { nodes.push(temp); temp=temp->left; } if(!nodes.empty()) { temp=nodes.top(); nodes.pop(); cout<<temp->val<<"\t"; temp=temp->right; } } }3)后序遍历
void postorder(TreeNode *root) //后序递归实现 { if(root==NULL) { return; } postorder(root->left); postorder(root->right); cout<<root->val<<"\t"; }非递归实现:后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。下面介绍一种网上看到比较容易理解的思路。实现过程如下:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。代码如下:
void postorder_stack(TreeNode *root) //后序非递归实现 { if(root==NULL) { return; } stack<TreeNode *> nodes; TreeNode *curNode; TreeNode *preNode=NULL; nodes.push(root); while(!nodes.empty()) { curNode=nodes.top(); if((curNode->left==NULL && curNode->right==NULL) || (preNode!=NULL &&(preNode==curNode->left || preNode==curNode->right))) { cout<<curNode->val<<"\t"; nodes.pop(); preNode=curNode; } else { if(curNode->right!=NULL) { nodes.push(curNode->right); } if(curNode->left!=NULL) { nodes.push(curNode->left); } } } }4)深度优先遍历
void width(TreeNode *root) //广度优先遍历 { if(root==NULL) { return; } queue<TreeNode *> nodes; nodes.push(root); TreeNode *temp; while(!nodes.empty()) { temp=nodes.front(); nodes.pop(); cout<<temp->val<<"\t"; if(temp->left!=NULL) { nodes.push(temp->left); } if(temp->right!=NULL) { nodes.push(temp->right); } } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/kevin_zhai/article/details/48025665