ODOA(2) 求二叉树中两个节点的最大距离(C语言实现)
问题描述;
如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离。
算法很容易想得到:
- 如果根节点的左子树或右子树为空,那么最大距离即为树的深度
- 否则,最大距离等于左子树的深度+右子树的深度
虽然这个问题很简单,但是在实现的时候,还树出了点问题,导致卡了两天才实现。
原因:
1 树的基本操作的实现不熟练
2 对递归的使用不熟悉
3 在递归建树的时候,输入序列一直没搞清楚。。
经验:
1 遇到树,首先想到的是递归处理
2 使用递归,一定要有一个终止条件
3 强类型语言真心不方便,比如节点值设置为整形,那么读入的一定要是整形(强制类型转换除外),导致必须要用一个数字(我用的0)表示空节点(即递归的终止条件)。
4 巩固了树的基本算法,是在这个问题上的最大的收获,只有真正实现它了,才能从更深的层次掌握它。
代码如下:
依然只是很简单的实现,并没有过多的异常处理。
/* Name: main.c Author: suzhou Date: 2014.02.18 Num. 2 */ #include "btree.h" int main() { BTree mytree = NULL; int choice; while (1) { printf("\n请选择您想要进行的操作:\n"); printf(" [ 1 ] 先序次序建立二叉树\n"); printf(" [ 2 ] 先序打印二叉树节点\n"); printf(" [ 3 ] 求树的深度\n"); printf(" [ 4 ] 求树中相距最远的两个节点的距离\n"); printf(" [ 0 ] 退出\n"); scanf("%d", &choice); switch(choice) { case 0: printf("%s\n", "谢谢使用"); exit(0); case 1: printf("%s", "请以先序遍历次序输入各个节点的数值:\n"); createBTree(&mytree); continue; case 2: preOrderVisit(mytree); continue; case 3: printf("树的深度为: %d\n", depth(mytree)); continue; case 4: printf("最大距离为: %d\n", maxDistance(mytree) ); continue; default: printf("%s\n", "请输入正确的选择"); continue; } } printf("Congratulations! It works!\n"); return 0; }
/* Name: btree.h Author: suzhou Date: 2014.02.18 Num. 2 */ #ifndef BTREE #define BTREE #include "stdio.h" #include "stdlib.h" typedef struct BTNode { int val; struct BTNode* pLeft; struct BTNode* pRight; }BTNode, *BTree; /* 建立二叉树 */ void createBTree ( BTree* tree ); /* 先序遍历二叉树 */ void preOrderVisit ( BTree tree ); /* 按树状打印节点 */ void printTree ( BTree tree, int depth ); /* * 求树的深度 */ int depth( BTree tree ); /* * 求树的两个节点的最远距离 */ int maxDistance( BTree tree ); #endif
/* Name: btree.c Author: suzhou Date: 2014.02.18 Num. 2 */ #include "btree.h" /* 建立二叉树 */ void createBTree ( BTree* tree ) { int val; scanf("%d", &val); if ( val == 0 ) { *tree = NULL; } else { *tree = (BTNode*) malloc (sizeof(BTNode)); (*tree)->val = val; createBTree(&((*tree)->pLeft)); createBTree(&((*tree)->pRight)); } } /* 先序遍历二叉树 */ void preOrderVisit ( BTree tree ) { if ( tree != NULL ) { printf("%d\n", tree->val); preOrderVisit(tree->pLeft); preOrderVisit(tree->pRight); } } /* 按树状打印节点 */ void printTree ( BTree tree, int depth ) { int i; if ( tree == NULL ) return; for ( i=depth; i>=0; i-- ) printf("%c", ' '); printf("%d\n" , tree->val); printTree(tree->pLeft, depth+1); printTree(tree->pRight, depth+1); } /* * 求树的深度 */ int depth( BTree tree ) { if (tree == NULL) return 0; else return 1 + (depth(tree->pLeft) >= depth(tree->pRight) ? depth(tree->pLeft) : depth(tree->pRight)); } /* * 求树的两个节点的最远距离 */ int maxDistance( BTree tree ) { if (tree->pLeft == NULL || tree->pRight == NULL) return depth(tree); else return depth(tree->pLeft) + depth(tree->pRight); }
运行截图: