三种顺序,前、中、后序。递归版的比较好写,但当树很大时容易导致栈溢出,因此,非递归版的才更有实用价值。参考网上的一些优秀例子,自己也写了下,对后序遍历做了改进。
用栈实现,模拟递归过程,前,中序不需要加标志位,而后序则麻烦一些,需要加标志位,标记节点是否二次入栈。
代码注释懒的写,直接把函数流程图画上来:
//代码
#include "
// HelloWorld.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <time.h> #include <math.h> #include <iomanip> void Print(int* R,int N) //打印二叉树数组 { for (int i=0;i<N;++i) { std::cout<<R[i]<<", "; } } typedef struct tagTREE { int val; tagTREE* left; tagTREE* right; tagTREE* parent; //一下次定义多个指针变量不行? bool isVisited; }TREE; template<class T> class Stack { private: typedef struct tagLINK { T val; tagLINK* pNext; }LINK; LINK* head; public: Stack():head(0){} void push( T t ) { LINK* pLINK = new LINK(); pLINK->val = t; pLINK->pNext = head; head = pLINK; } T pop() { if (head != NULL) { T val = head->val; LINK* temp = head->pNext; delete head; head = temp; return val; } return NULL; } bool empty() { return head ? false : true; } }; //按数组里指定的数值生成任意二叉树结构,数组里缺失的数值表示该索引的节点没有 void CreateTree(TREE** node, int a[], int N ) { //预处理,记录节点在全部节点中的索引,而不是其真正位置号 cout<<endl; int* arr = new int[a[N-1]]; for (int i=0;i<a[N-1];++i) { arr[ i ] = 0; } int k=0; for (int i=0;i<N;++i) { arr[ a[i]-1 ] = i; } TREE* arrTree = new TREE[N]; //root arrTree[0].parent = NULL; for (int i=1;i<=N;++i) { arrTree[i-1].val = a[i-1]; arrTree[i-1].isVisited = false; int parentIdx = int(a[i-1] / 2); if( parentIdx == 0 ) arrTree[i-1].parent = NULL; else arrTree[i-1].parent = &arrTree[ arr[ parentIdx-1 ] ]; int leftIdx = int(a[i-1] * 2 ); int rightIdx = leftIdx + 1; if ( leftIdx > a[N-1] || arr[leftIdx-1] == 0 ) { arrTree[i-1].left = NULL; } else { arrTree[i-1].left = &arrTree[ arr[ leftIdx-1 ] ]; } if ( rightIdx > a[N-1] || arr[rightIdx-1] == 0 ) { arrTree[i-1].right = NULL; } else { arrTree[i-1].right = &arrTree[ arr[ rightIdx-1 ] ]; } } *node = arrTree; //test for (int i=1;i<=N;++i) { cout<<"val="<<arrTree[i-1].val; cout<<" left="; if (arrTree[i-1].left) { cout<<arrTree[i-1].left->val; } cout<<" right="; if (arrTree[i-1].right) { cout<<arrTree[i-1].right->val; } cout<<" parent="; if (arrTree[i-1].parent) { cout<<arrTree[i-1].parent->val; } cout<<endl; } } void NonRecursePreorder(TREE* node) { Stack<TREE*> stk; while( node || !stk.empty() ) { while(node) { cout<<node->val<<","; if( node->right ) stk.push(node->right); node = node->left; } node = stk.pop(); } } void NonRecurseInorder(TREE* node) { Stack<TREE*> stk; while( node || !stk.empty()) { while(node) //当节点存在时,先将它入栈,然后不停的索引左子节点 { stk.push(node); node = node->left; } //当无左子节点时,最后一个入栈的节点正是要访问的 node = stk.pop(); cout<<node->val<<","; node = node->right; //取出右节点,返回循环,如果右节点为空,则需要继续出栈 } } void NonRecursePostorder(TREE* node) { Stack<TREE*> stk; while (node || !stk.empty()) { while(node) { stk.push(node); node = node->left; } node = stk.pop(); if (!node->isVisited) { if (node->right) { node->isVisited = true; stk.push(node); node = node->right; continue; } } cout<<node->val<<","; node = NULL; } } int _tmain(int argc, _TCHAR* argv[]) { const int M = 16; int arr[M] = { 1,2,3,4,5,7,8,9,11,14,15,17,18,23,28,29 }; TREE* node; CreateTree(&node,arr,M); cout<<"Mid:"<<endl; NonRecurseInorder(node); cout<<"Front:"<<endl; NonRecursePreorder(node); cout<<"Back:"<<endl; NonRecursePostorder(node); return 0; }输出结果:
val=1 left=2 right=3 parent=
val=2 left=4 right=5 parent=1
val=3 left= right=7 parent=1
val=4 left=8 right=9 parent=2
val=5 left= right=11 parent=2
val=7 left=14 right=15 parent=3
val=8 left= right=17 parent=4
val=9 left=18 right= parent=4
val=11 left= right=23 parent=5
val=14 left=28 right=29 parent=7
val=15 left= right= parent=7
val=17 left= right= parent=8
val=18 left= right= parent=9
val=23 left= right= parent=11
val=28 left= right= parent=14
val=29 left= right= parent=14
Mid:
8,17,4,18,9,2,5,11,23,1,3,28,14,29,7,15,Front:
1,2,4,8,17,9,18,5,11,23,3,7,14,28,29,15,Back:
17,8,18,9,4,23,11,5,2,28,29,14,15,7,3,1,请按任意键继续. . .
参考文献:
http://blog.csdn.net/kofsky/article/details/2886453