树——二叉树的先序中序和后序遍历
Posted dishengandziyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树——二叉树的先序中序和后序遍历相关的知识,希望对你有一定的参考价值。
1,二叉树是否只有一种遍历方式(层次遍历)?
2,典型的二叉树的遍历方式:
1,先序遍历(Pre-Order Traversal);
2,中序遍历(In-Order Traversal);
3,后序遍历(Post-Order Traversal);
3,先序遍历(“先序”指最先访问根结点中的数据元素):
1,二叉树为空:
1,无操作,直接返回;
2,二叉树不为空:
1,访问根结点中的数据元素;
2,先序遍历左子树;
3,先序遍历右子树;
4,先序遍历功能定义及其代码实现:
1,代码示例:
1 preOrderTraversal(node) 2 { 3 if( noe != NULL ) 4 { 5 access(node->value); 6 preOrderTraversal(node->left); 7 preOrderTraversal(node->right); 8 } 9 }
2,功能函数代码实现:
1 /* 实现先序遍历,队里里面保存的数据元素用来反应遍历时候结点次序 */ 2 void PreOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue) 3 { 4 if( node != NULL ) 5 { 6 queue.add(node); // 访问中间结点 7 PreOrderTraversal(node->left, queue); 8 PreOrderTraversal(node->right, queue); 9 } 10 }
5,中序遍历(“中序”指中间访问根结点中的数据元素):
1,二叉树为空:
1,无操作,直接返回;
2,二叉树不为空:
1,中序遍历左子树;
2,访问根结点中的数据元素;
3,中序遍历右子树;
6,中序遍历功能定义:
1,代码示例:
1 inOrderTraversal(node) 2 { 3 if(node != NULL) 4 { 5 inOrderTraversal(node->left); 6 access(node->value); 7 inOrderTraversal(node->right); 8 } 9 }
2,功能函数代码实现:
1 /* 实现中序遍历,队里里面保存的数据元素用来反应遍历时候结点次序 */ 2 void inOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue) 3 { 4 if( node != NULL ) 5 { 6 inOrderTraversal(node->left, queue); 7 queue.add(node); // 访问中间结点 8 inOrderTraversal(node->right, queue); 9 } 10 }
7,后续遍历(“后序”指最后访问根结点中的数据元素):
1,二叉树为空:
1,无操作,直接返回;
2,二叉树不为空:
1,后序遍历左子树;
2,后序遍历右子树;
3,访问根结点中的数据元素;
8,后续遍历功能定义:
1,代码示例:
1 postOrderTraversal(node) 2 { 3 if( node != NULL ) 4 { 5 postOrderTraversal(node->left); 6 postOrderTraversal(node->right); 7 access(node->value); 8 } 9 }
2,功能函数代码实现:
1 /* 实现后序遍历,队里里面保存的数据元素用来反应遍历时候结点次序 */ 2 void postOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue) 3 { 4 if( node != NULL ) 5 { 6 postOrderTraversal(node->left, queue); 7 postOrderTraversal(node->right, queue); 8 queue.add(node); // 访问中间结点 9 } 10 }
9,需要考虑的问题:
1,是否可以将二叉树的典型便利算法集成到 BTree 中?如果可以,代码需要做怎样的改动?
10,设计要点:
1,不能与层次遍历函数冲突,必须设计新的函数接口;
2,算法执行完成后,能够方便的获取遍历结果;
3,遍历结果能够反映结点访问的先后次序;
11,函数接口设计:
1,SharedPointer<Array<T> > traversal(BTTraversal order):
1,根据参数 order 选择执行遍历算法(先序,中序,后序);
2,返回值为堆空间中的数组对象(生命周期由智能指针管理);
3,数组元素的次序反映遍历的先后次序;
12,典型遍历示例:
13,遍历算法成员函数实现:
1,定义遍历方式:
1 /* 定义排序的方式 */ 2 enum BTTraversal 3 { 4 PreOrder, 5 InOrder, 6 PostOrder, 7 LevelOrder // 重构了“树——二叉树线索化”中的层次遍历次序 8 };
2,遍历的功能函数:
1 /* 遍历的功能函数,第二个参数用于保存访问时,结点的先后顺序 */ 2 void traversal(BTTraversal order, LinkQueue<BTreeNode<T>*>& queue) 3 { 4 switch(order) 5 { 6 case PreOrder: 7 PreOrderTraversal(root(), queue); 8 break; 9 case InOrder: 10 inOrderTraversal(root(), queue); 11 break; 12 case PostOrder: 13 postOrderTraversal(root(), queue); 14 Break; 15 default: 16 THROW_EXCEPTION(InvalidParameterException, "Parameter order is invalid ..."); 17 break; 18 } 19 }
3,遍历的实现:
1 /* 典型的二叉树遍历,前序、中序、后续 */ 2 SharedPointer< Array<T> > traversal(BTTraversal order) 3 { 4 DynamicArray<T>* ret = NULL; 5 LinkQueue<BTreeNode<T>*> queue; // 保存遍历结点次序,用 queue 来传递元素的值是一个很好的抉择; 6 7 traversal(order, queue); // 执行功能函数 8 9 ret = new DynamicArray<T>(queue.length()); // 申请动态数组 10 11 if( ret != NULL ) // 保存遍历所得的动态数组 12 { 13 /* 将队列中,结点里面数据元素的值,依次放到返回数组里面 */ 14 for(int i=0; i<ret->length(); i++, queue.remove()) // 这里不要忘了将队列依次删除首元素 15 { 16 ret->set(i, queue.front()->value); // 将结点里面数据元素值依次放到返回数组里面 17 } 18 } 19 else 20 { 21 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create return array ..."); 22 } 23 24 return ret; 25 }
14,小结:
1,二叉树的典型遍历都是以递归方式执行的;
2,BTree 以不同的函数接口支持典型遍历;
3,层次遍历与典型遍历互不冲突;
4,遍历结果能够反映树结点访问的先后次序;
以上是关于树——二叉树的先序中序和后序遍历的主要内容,如果未能解决你的问题,请参考以下文章