二叉树遍历

遍历命名

根据访问结点操作发生位置命名:
① NLR:前序遍历(Preorder Traversal 亦称(先序遍历))
——访问根结点的操作发生在遍历其左右子树之前。
② LNR:中序遍历(Inorder Traversal)
——访问根结点的操作发生在遍历其左右子树之中(间)。
③ LRN:后序遍历(Postorder Traversal)
——访问根结点的操作发生在遍历其左右子树之后。
注意:
由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

遍历算法

1.先(根)序遍历的递归算法定义:
若二叉树非空,则依次执行如下操作:
⑴ 访问根结点;
⑵ 遍历左子树;
⑶ 遍历右子树。
2.中(根)序遍历的递归算法定义:
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵访问根结点;
⑶遍历右子树。
3.后(根)序遍历得递归算法定义:
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵遍历右子树;
⑶访问根结点。

中序算法实现

用二叉链表做为存储结构,中序遍历算法可描述为:
void InOrder(BinTree T)
{ //算法里①~⑥是为了说明执行过程加入的标号
① if(T) { // 如果二叉树非空
② InOrder(T->lchild);
③ printf("%c",T->data); // 访问结点
④ InOrder(T->rchild);
⑤ }
⑥ } // InOrder

中序投影法

计算中序遍历拥有比较简单直观的投影法,如图
中序遍历的投影法中序遍历的投影法

层序遍历

除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

递归实现

编辑
在这里,所有的二叉树都以数组的形式储存。

前序遍历

1
2
3
4
5
6
7
8
9
10
11
procedure first(i:longint);
 
begin
 
write(a[i]);
 
ifa[i*2]<>0then first(i*2);
 
ifa[i*2+1]<>0then first(i*2+1);
 
end;

中序遍历

1
2
3
4
5
6
7
8
9
10
11
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;

后序遍历

1
2
3
4
5
6
7
8
9
10
11
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。
二叉链表基本思想
基于先序遍历的构造,即以二叉树的先序序列为输入构造。
注意:
先序序列中必须加入虚结点以示空指针的位置。
【例】
建立上图所示二叉树,其输入的先序序列是:ABD∮∮∮CE∮∮F∮∮。
构造算法
假设虚结点输入时以空格字符表示,相应的构造算法为:
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); //构造右子树 }}
注意:
调用该算法时,应将待建立的二叉链表的根指针的地址作为实参。
示例
设root是一根指针(即它的类型是BinTree),则调用CreateBinTree(&root)后root就指向了已构造好的二叉链表的根结点。
二叉树建立过程见
下面是关于二叉树的遍历、查找、删除、更新数据的代码(递归算法):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include<iostream>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<map>
#include<set>
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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章