编程之美之求二叉树中节点的最大距离(递归和非递归法)
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;}
相关文章推荐
- 第六章:面向对象(二)
- MQTT简要介绍
- 第四章:数组
- C# 内存操作
- ubuntu下用命令行安装Qt
- 第三章:java流程语句
- JavaSe:Cookie 管理的API介绍
- 第二章:java语法
- Java基础——switch、循环语句、控制跳转语句
- 馋-c语言的规则
- java(1)--集合框架
- C++对象模型系列集合
- C++ STL The compare function
- 如何较好的使用BoxLayout
- java获取路径的各种方法
- 文章推荐集合页推荐学习Python Django 开发机开发人参考
- Java与C语言的不同
- Java解析XML之dom4j方式
- Spring第一餐
- C++Primer第五版 第10章 泛型算法(练习解答)