标题：二叉树遍历
算法实现
遍历方案  二叉树的前序遍历从二叉树的递归定义可知，一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此，在任一给定结点上，可以按某种次序执行三
个操作：
⑴访问结点本身（N），
⑵遍历该结点的左子树（L），
⑶遍历该结点的右子树（R）。
以上三种操作有六种执行次序：
NLR、LNR、LRN、NRL、RNL、RLN。
注意：
前三种次序与后三种次序对称，故只讨论先左后右的前三种次序。遍历命名根据访问结点操作发生位置命名：
① NLR：前序遍历(PreorderTraversal亦称（先序遍历））
——访问根结点的操作发生在遍历其左右子树之前。
② LNR：中序遍历(InorderTraversal)
——访问根结点的操作发生在遍历其左右子树之中（间）。
③ LRN：后序遍历(PostorderTraversal)
——访问根结点的操作发生在遍历其左右子树之后。
注意：
由于被访问的结点必是某子树的根，所以N(Node）、L(Left subtree）和R(Right subtree）又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。遍历算法1．中序遍历的递归算法定义：
若二叉树非空，则依次执行如下操作：
⑴遍历左子树；
⑵访问根结点；
⑶遍历右子树。
2．先序遍历的递归算法定义：
若二叉树非空，则依次执行如下操作：
⑴ 访问根结点；
⑵ 遍历左子树；
⑶ 遍历右子树。
3．后序遍历得递归算法定义：
若二叉树非空，则依次执行如下操作：
⑴遍历左子树；
⑵遍历右子树；
⑶访问根结点。
4．层次遍历中序算法实现用二叉链表做为存储结构，中序遍历算法可描述为： 
void InOrder(BinTree T)
{ //算法里①~⑥是为了说明执行过程加入的标号
① if(T) { // 如果二叉树非空
② InOrder(T->lchild）；
③ printf("%c"，T->data）； // 访问结点
④ InOrder(T->rchild);
⑤ }
⑥ } // InOrder中序投影法计算中序遍历拥有比较简单直观的投影法，如图
  中序遍历的投影法遍历序列1．遍历二叉树的执行踪迹
三种递归遍历算法的搜索路线相同（如下图虚线所示）。
具体线路为：
从根结点出发，逆时针沿着二叉树外缘移动，对每个结点均途径三次，最后回到根结点。
2．遍历序列 
  
图
⑴ 中序序列（inorder traversal）
中序遍历二叉树时，对结点的访问次序为中序序列
【例】中序遍历上图所示的二叉树时，得到的中序序列为：
D B A E C F
⑵ 先序序列（preorder traversal）
先序遍历二叉树时，对结点的访问次序为先序序列
【例】先序遍历上图所示的二叉树时，得到的先序序列为：
A B D C E F
⑶ 后序序列（postorder traversal）
后序遍历二叉树时，对结点的访问次序为后序序列
【例】后序遍历上图所示的二叉树时，得到的后序序列为：
D B E F C A
⑷层序遍历（level traversal）二叉树的操作定义为：若二叉树为空，则退出，否则，按照树的结构，从根开始自上而下，自左而右访问每一个结点，从而实现对每一个结点的遍历
【例】层序遍历上图所示的二叉树时，得到的层序序列为：
A B C D E F层序遍历除了先序遍历、中序遍历、后序遍历外，还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1，层序遍历就是从所在二叉树的根节点出发，首先访问第一层的树根节点，然后从左到右访问第2层上的节点，接着是第三层的节点，以此类推，自上而下，自左至右逐层访问树的结点的过程就是层序遍历。
递归实现
在这里，所有的二叉树都以数组的形式储存。前序遍历procedure first(i:longint);
begin
write(a[i]);
if a[i*2]<>0 then first(i*2）；
if a[i*2+1]<>0 then first(i*2+1）；
end;中序遍历procedure mid(i:longint);
begin
if a[i*2]<>0 then mid(i*2）；
write(a[i]);
if a[i*2+1]<>0 then mid(i*2+1）；
end;后序遍历procedure last(i:longint);
begin
if a[i*2]<>0 then last(i*2）；
if a[i*2+1]<>0 then last(i*2+1）；
write(a[i]);
end;
注意事项
⑴在搜索路线中，若访问结点均是第一次经过结点时进行的，则是前序遍历；若访问结点均是在第二次（或第三次）经过结点时进行的，则是中序遍历（或后序遍历）。只要将搜索路线上所有在第一次、第二次和第三次经过的结点分别列表，即可分别得到该二叉树的前序序列、中序序列和后序序列。
⑵上述三种序列都是线性序列，有且仅有一个开始结点和一个终端结点，其余结点都有且仅有一个前驱结点和一个后继结点。为了区别于树形结构中前驱（即双亲）结点和后继（即孩子）结点的概念，对上述三种线性序列，要在某结点的前驱和后继之前冠以其遍历次序名称。
【例】上图所示的二叉树中结点C，其前序前驱结点是D，前序后继结点是E；中序前驱结点是E，中序后继结点是F；后序前驱结点是F，后序后继结点是A。但是就该树的逻辑结构而言，C的前驱结点是A，后继结点是E和F。
二叉链表
1． 基本思想基于先序遍历的构造，即以二叉树的先序序列为输入构造。
注意：
先序序列中必须加入虚结点以示空指针的位置。
【例】
建立上图所示二叉树，其输入的先序序列是：ABD∮∮∮CE∮∮F∮∮。2． 构造算法假设虚结点输入时以空格字符表示，相应的构造算法为：
void CreateBinTree (BinTree **T)
{ //构造二叉链表。T是指向根指针的指针，故修改*T就修改了实参（根指针）本身
char ch；
if((ch=getchar())=='') *T=NULL； //读入空格，将相应指针置空 
else{ //读人非空格
*T=(BinTNode *)malloc(sizeof(BinTNode））； //生成结点
（*T)->data=ch；
CreateBinTree(&(*T)->lchild）； //构造左子树
CreateBinTree(&(*T)->rchild）； //构造右子树
}
}
注意：
调用该算法时，应将待建立的二叉链表的根指针的地址作为实参。3． 示例设root是一根指针（即它的类型是BinTree），则调用CreateBinTree(&root）后root就指向了已构造好的二叉链表的根结点。
二叉树建立过程见
下面是关于二叉树的遍历、查找、删除、更新数据的代码（递归算法）：
#include <iostream>
using namespace std;
typedef int T;
class bst{
struct Node{
T data;
Node* L;
Node* R;
Node(const T& d,Node* lp=NULL,Node* rp=NULL):data(d),L(lp),R(rp){}
};
Node* root;
int num;
public:
bst():root(NULL),num(0){}
void clear(Node* t){
if(t==NULL) return;
clear(t->L);
clear(t->R);
delete t;
}
~bst(){clear(root);}
void clear(){
clear(root);
num = 0;
root = NULL;
}
bool empty(){return root==NULL;}
int size(){return num;}
T getRoot(){
if(empty()) throw "empty tree";
return root->data;
}
void travel(Node* tree){
if(tree==NULL) return;
travel(tree->L);
cout << tree->data << ' ';
travel(tree->R);
}
void travel(){
travel(root);
cout << endl;
}
int height(Node* tree){
if(tree==NULL) return 0;
int lh = height(tree->L);
int rh = height(tree->R);
return 1+(lh>rh?lh:rh);
}
int height(){
return height(root);
}
void insert(Node*& tree,const T& d){
if(tree==NULL)
tree = new Node(d);
else if(ddata)
insert(tree->L,d);
else
insert(tree->R,d);
}
void insert(const T& d){
insert(root,d);
num++;
}
Node*& find(Node*& tree,const T& d){
if(tree==NULL) return tree;
if(tree->data==d) return tree;
if(ddata)
return find(tree->L,d);
else
return find(tree->R,d);
}
bool find(const T& d){
return find(root,d)!=NULL;
}
bool erase(const T& d){
Node*& pt = find(root,d);
if(pt==NULL) return false;
combine(pt->L,pt->R);
Node* p = pt;
pt = pt->R;
delete p;
num--;
return true;
}
void combine(Node* lc,Node*& rc){
if(lc==NULL) return;
if(rc==NULL) rc = lc;
else combine(lc,rc->L);
}
bool update(const T& od,const T& nd){
Node* p = find(root,od);
if(p==NULL) return false;
erase(od);
insert(nd);
return true;
}
};
int main()
{
bst b;
cout << "input some integers:";
for(;;){
int n;
cin >> n;
b.insert(n);
if(cin.peek()=='\n') break;
}
（）；
for(;;){
cout << "input data pair:";
int od,nd;
cin >> od >> nd;
if(od==-1&&nd==-1） break;
b.update(od,nd);
（）；
}
}