您的位置:首页 > 编程语言

编程之美之求二叉树中节点的最大距离(递归和非递归法)

2015-09-19 09:13 267 查看
原文链接:http://blog.chinaunix.net/uid-25254574-id-2141324.html
#include
#include

using namespace std;

//*************************************

//题目:

//     求一棵二叉树中距离相差最远的两个结点之间的距离。

//

//

//思路:注意指针声明了一定要赋值,否则会报错。

//        方法一:递归法

//距离相差最远的两个结点,共有以下两种情况:

//
(1)路径经过根结点,所以两个结点在根结点的不同分支上

//
(2)路径不经过根结点,所以两个结点应该是次根结点中相聚最远的两个结点。
(递归思想)
//
递归本质上还是采用了后续遍历的方法。由于是从叶子结点开始的所以每次处理都
是第一种情况。// 方法二:非递归法//采用后序遍历二叉树的同时对二叉树的结点进行更新,每次更新都要更新最大距离。
//

//*************************************

//

//定义结点结构

//

struct NODE

{

NODE* pLeft;

NODE* pRight;

int nMaxLeft;

int nMaxRight;

char nValue;

};

int tMaxLength=0;    //最大距离

stack<NODE*> s;

//

//求最大距离(方法一)

//

void findMaxLength1(NODE* root)

{

//递归结束

if(root==NULL)    return;
    ////左树为空//if(root->pLeft==NULL)root->nMaxLeft=0;////右树为空//if(root->pRight==NULL)root->pRight=0;////左树不为空//if(root->pLeft!=NULL){findMaxLength1(root->pLeft);}////右树不为空//if(root->pRight!=NULL){findMaxLength1(root->pRight);}////求左子树最大距离//if(root->pLeft!=NULL){int nTempMax=0;if(root->pLeft->nMaxLeft>root->pLeft->nMaxRight)nTempMax=root->pLeft->nMaxLeft;elsenTempMax=root->pLeft->nMaxRight;root->nMaxLeft=nTempMax+1;}////求右子树最大距离//if(root->pRight!=NULL){int nTempMax=0;if(root->pRight->nMaxLeft>root->pRight->nMaxRight)nTempMax=root->pRight->nMaxLeft;elsenTempMax=root->pRight->nMaxRight;root->nMaxRight=nTempMax+1;}////更新最大距离//if((root->nMaxLeft+root->nMaxRight)>tMaxLength)tMaxLength=root->nMaxLeft+root->nMaxRight;}////求最大距离(方法二)//void findMaxLength2(NODE* root){NODE *p=root;NODE *have_visited=NULL; //记录上次访问的结点,主要是用在:判定根结点是
//
否能访问。如果根结点的右孩子是刚访问的,那么就能访问根结点了。
    while(p!=NULL||!s.empty()){////把最左分支压入栈,类似于中序遍历//while(p!=NULL){s.push(p);p=p->pLeft;}p=s.top();////如果右子树是空,那么后序遍历就是中序遍历//如果如果上次访问的是右结点,那么可以访问根结点//if(p->pRight==NULL||have_visited==p->pRight){////以下是求最大距离的代码,不属于后序遍历//if(p->pLeft!=NULL){p->nMaxLeft=p->pLeft->nMaxLeft+1;if(p->pLeft->nMaxRight+1>p->nMaxLeft)p->nMaxLeft=p->pLeft->nMaxRight+1;}if(p->pRight!=NULL){p->nMaxRight=p->pRight->nMaxRight+1;if(p->pRight->nMaxLeft+1>p->nMaxRight)p->nMaxRight=p->pRight->nMaxLeft+1;}if((root->nMaxLeft+root->nMaxRight)>tMaxLength)tMaxLength=root->nMaxLeft+root->nMaxRight;//*************************************结束s.pop();have_visited=p;p=NULL;}else{p=p->pRight; //指向右子树,为下次循环,压栈做准备。}}}////中序遍历//void inOrderTraverse(NODE* root){s.push(root);while(!s.empty()){while(s.top()!=NULL){NODE* t=s.top()->pLeft;s.push(t);}s.pop();if(!s.empty()){NODE* top=s.top();s.pop();printf("%d ",top->nValue);s.push(top->pRight);}}}////后序遍历//void postOrderTraverse(NODE* root){NODE *p=root;NODE *have_visited=NULL; //记录上次访问的结点,主要是用在:判定根结点是
//
否能访问如果根结点的右孩子是刚访问的,那么就能访问根结点了。
    while(p!=NULL||!s.empty()){////把最左分支压入栈,类似于中序遍历//while(p!=NULL){s.push(p);p=p->pLeft;}p=s.top();////如果右子树是空,那么后序遍历就是中序遍历//如果如果上次访问的是右结点,那么可以访问根结点//if(p->pRight==NULL||have_visited==p->pRight){printf("%d ",p->nValue);s.pop();have_visited=p;p=NULL;}else{p=p->pRight; //指向右子树,为下次循环,压栈做准备。}}}
////初始化树//NODE* initTree(){NODE* tree[10];for(int i=0;i<10;i++){tree[i]=(NODE*)malloc(sizeof(NODE));tree[i]->nMaxLeft=0;tree[i]->nMaxRight=0;tree[i]->pLeft=NULL;tree[i]->pRight=NULL;tree[i]->nValue=(char)i;}for(int i=0;i<=2;i++){tree[i]->pLeft=tree[2*i+1];tree[i]->pRight=tree[2*i+2];}tree[3]->pLeft=tree[7];tree[5]->pRight=tree[8];return tree[0];}int main(){printf("后序遍历:");postOrderTraverse(initTree());printf("\n");printf("中序遍历:");inOrderTraverse(initTree());printf("\n");findMaxLength2(initTree());printf("非递归:%d\n",tMaxLength);findMaxLength1(initTree());printf("递归法:%d\n",tMaxLength);return 0;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: