问题描述;
如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离。
算法很容易想得到:
如果根节点的左子树或右子树为空,那么最大距离即为树的深度
否则,最大距离等于左子树的深度+右子树的深度
虽然这个问题很简单,但是在实现的时候,还树出了点问题,导致卡了两天才实现。
原因:
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);
}
运行截图: