二叉树遍历的算法实现

如题所述

第1个回答  2016-05-11

从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
⑴访问结点本身(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.后(根)序遍历得递归算法定义:
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵遍历右子树;
⑶访问根结点。 用二叉链表做为存储结构,中序遍历算法可描述为:
void InOrder(BinTree T)
{ //算法里①~⑥是为了说明执行过程加入的标号
① if(T) { // 如果二叉树非空
② InOrder(T->lchild);
③ printf(%c,T->data); // 访问结点
④ InOrder(T->rchild);
⑤ }
⑥ } // InOrder 计算中序遍历拥有比较简单直观的投影法,如图
⑴在搜索路线中,若访问结点均是第一次经过结点时进行的,则是前序遍历;若访问结点均是在第二次(或第三次)经过结点时进行的,则是中序遍历(或后序遍历)。只要将搜索路线上所有在第一次、第二次和第三次经过的结点分别列表,即可分别得到该二叉树的前序序列、中序序列和后序序列。
⑵上述三种序列都是线性序列,有且仅有一个开始结点和一个终端结点,其余结点都有且仅有一个前驱结点和一个后继结点。为了区别于树形结构中前驱(即双亲)结点和后继(即孩子)结点的概念,对上述三种线性序列,要在某结点的前驱和后继之前冠以其遍历次序名称。
【例】上图所示的二叉树中结点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就指向了已构造好的二叉链表的根结点。
二叉树建立过程见
下面是关于二叉树的遍历、查找、删除、更新数据的代码(递归算法): #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);    }}