参照:http://blog.csdn.net/caryaliu/article/details/8107089
参照:http://blog.csdn.net/lalor/article/details/7626678
把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两个节点之间的个数。
写一个程序求一棵二叉树中相距最远的两个节点之间的距离。
如下图所示,粗箭头的边表示最长距离:
树中相距最远的两个节点是A, B
分析可知:对于二叉树,若要两个节点U,V相距最远,有两种情况:
1,从U节点到V节点之间的路径经过根节点
2,从U节点到V节点之间的路径不经过根节点,这种情况下,U,V节点必定在根节点的左子树或者右子树上,这样就转化为求以根节点的孩子节点为根节点的二叉树中最远的两个节点间的距离
上面所说的经过根节点,是指路径中包含根节点,例如:加入上图中只有左子树FGHA, 那么最长距离的两个节点是F, A,该路径中包含根节点F,也称为经过根节点。
于是我们可以递归求解,按照二叉树的中序遍历方式遍历二叉树,在遍历的过程中寻找相距最远的两个节点。
解法1:- #include <iostream>
- #include <stdlib.h>
- using namespace std;
- struct BinaryTreeNode
- {
- int m_nValue;
- struct BinaryTreeNode *m_pLeft;
- struct BinaryTreeNode *m_pRight;
- };
- int maxDistance(BinaryTreeNode *root, int *max);
- int DistanceCore(BinaryTreeNode *root,int *max);
- //后序遍历,用于我们建立的二叉树是否正确
- void Traverse( BinaryTreeNode * root);
- BinaryTreeNode* Construct(int *preorder, int *inorder, int lenght);
- BinaryTreeNode* ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder);
- int InsertNodeAtMostRight(BinaryTreeNode * root, BinaryTreeNode * node);
- int main(int argc, char* argv[])
- {
- int preOrder[] = {5, 4, 8, 9, 6, 3, 18, 19, 2};
- int inOrder[] = {9, 8, 6, 3, 4, 5, 19, 18, 2};
- int max;
- //建树
- BinaryTreeNode *parent = Construct(preOrder, inOrder, sizeof(inOrder) / sizeof(inOrder[0]));
- cout << "A树的后序遍历的结果:" << endl;
- Traverse(parent);
- cout << endl;
- BinaryTreeNode *node1 = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
- BinaryTreeNode *node2 = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
- node1->m_nValue = 0;
- node1->m_pLeft = NULL;
- node1->m_pRight = NULL;
- node2->m_nValue = 0;
- node2->m_pLeft = NULL;
- node2->m_pRight = NULL;
- maxDistance(parent, &max);
- cout <<"max distance of tree's nodes : " << max << endl;
- InsertNodeAtMostRight(parent, node1);
- maxDistance(parent, &max);
- cout <<"max distance of tree's nodes after insert node1: " << max << endl;
- InsertNodeAtMostRight(parent, node2);
- maxDistance(parent, &max);
- cout <<"max distance of tree's nodes after insert node2: " << max << endl;
- //测试极端情况,即只有一个节点
- maxDistance(node2, &max);
- cout <<"just one node " << max << endl;
- //测试极端情况,即只有二个节点
- maxDistance(node1, &max);
- cout <<"just two node " << max << endl;
- return 0;
- }
- BinaryTreeNode* Construct(int *preorder, int *inorder, int lenght)
- {
- if (preorder == NULL || inorder == NULL || lenght <= 0)
- {
- return NULL;
- }
- return ConstructCore(preorder, preorder + lenght - 1, inorder, inorder + lenght - 1);
- }
- BinaryTreeNode* ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder)
- {
- int rootValue = startPreorder[0];
- BinaryTreeNode *root = new BinaryTreeNode();
- root->m_nValue = rootValue;
- root->m_pLeft = root->m_pRight = NULL;
- if (startPreorder == endPreorder)
- {//先序遍历已经结束了,那这个时候一定是插入最后一个节点,则应该满足下面的if语句,否则输入的数据有误
- if (startInorder == endInorder && *startPreorder == *startInorder)
- {
- return root;
- }
- else
- {
- cout << "Invalid input" << endl;
- exit(-1);
- }
- }
- int *rootInorder = startInorder;
- while (rootInorder <= endInorder && *rootInorder != rootValue)
- {
- ++rootInorder;
- }
- if (rootInorder <= endInorder && *rootInorder != rootValue)
- {
- cout << "Invalid input" << endl;
- exit(-1);
- }
- int leftLength = rootInorder - startInorder;
- int *leftPreorderEnd = startPreorder + leftLength;
- if (leftLength > 0)
- {
- root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1);
- }
- if (leftLength < endPreorder - startPreorder)
- {
- root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder);
- }
- return root;
- }
- void Traverse( BinaryTreeNode * root)
- {
- if (root == NULL)
- {
- return;
- }
- else
- {
- Traverse(root->m_pLeft);
- Traverse(root->m_pRight);
- cout << root->m_nValue << " ";
- }
- }
- int maxDistance(BinaryTreeNode *root, int *max)
- {
- //这个函数的主要功能是判断root不为空,且给max赋初值
- if (root == NULL || max == NULL)
- {
- return -1;
- }
- *max = 0;
- return DistanceCore(root, max);
- }
- int DistanceCore(BinaryTreeNode *root, int *max)
- {
- //如果节点是叶子节点,则返回0——深度
- if (root->m_pLeft == NULL && root->m_pRight == NULL)
- {
- return 0;
- }
- //保存左右子树的最大深度
- int lDistance = 0;
- int rDistance = 0;
- //左子树不为空,返回当前节点到左子树的最大深度
- if (root->m_pLeft != NULL)
- {
- lDistance = 1 + DistanceCore(root->m_pLeft, max);
- }
- if (root->m_pRight != NULL)
- {
- rDistance = 1 + DistanceCore(root->m_pRight, max);
- }
- //遍历到当前节点时,能获得的最大距离
- if (lDistance + rDistance > *max)
- {
- //保存当前获得的最大距离
- *max = lDistance + rDistance;
- }
- //返回左右子树中,深度较大的一个
- return lDistance > rDistance ? lDistance : rDistance;
- }
- //为了测试程序写的辅助函数,在树的最最右边插入一个新的节点
- int InsertNodeAtMostRight(BinaryTreeNode * root, BinaryTreeNode * node)
- {
- if (root == NULL || node == NULL)
- {
- return -1;
- }
- while (root->m_pRight != NULL)
- {
- root = root->m_pRight;
- }
- root->m_pRight = node;
- return 0;
- }
- #include <stdlib.h>
- #include <stdio.h>
- typedef struct Node {
- struct Node *pleft; //左孩子
- struct Node *pright; //右孩子
- char chValue; //该节点的值
- int leftMaxValue; //左子树最长距离
- int rightMaxValue; //右子树最长距离
- }LNode, *BinTree;
- void findMaxLen(BinTree root, int *maxLen) {
- //遍历到叶子结点,返回
- if(root == NULL)
- return;
- //如果左子树为空,那么该节点左边最长距离为0
- if(root->pleft == NULL)
- root->leftMaxValue = 0;
- //如果右子树为空,那么该节点右边最长距离为0
- if(root->pright == NULL)
- root->rightMaxValue = 0;
- //如果左子树不为空,递归寻找左子树最长距离
- if(root->pleft != NULL)
- findMaxLen(root->pleft, maxLen);
- //如果右子树不为空,递归寻找右子树最长距离
- if(root->pright != NULL)
- findMaxLen(root->pright, maxLen);
- //计算左子树中距离根节点的最长距离
- if(root->pleft != NULL) {
- if(root->pleft->leftMaxValue > root->pleft->rightMaxValue)
- root->leftMaxValue = root->pleft->leftMaxValue + 1;
- else
- root->leftMaxValue = root->pleft->rightMaxValue + 1;
- }
- //计算右子树中距离根节点的最长距离
- if(root->pright != NULL) {
- if(root->pright->leftMaxValue > root->pright->rightMaxValue)
- root->rightMaxValue = root->pright->leftMaxValue + 1;
- else
- root->rightMaxValue = root->pright->rightMaxValue + 1;
- }
- //更新最长距离
- if(root->leftMaxValue + root->rightMaxValue > *maxLen)
- *maxLen = root->leftMaxValue + root->rightMaxValue;
- }
- //创建二叉树
- void buildBinTree(BinTree *root)
- {
- char ch;
- scanf("%c", &ch); //输入一个元素
- fpurge(stdin);
- if(ch == ' ') //若输入的是空格符,表明二叉树为空,置*root为NULL
- *root = NULL;
- else { //若输入的不是空格符,则将该值赋值给根节点的chValue, 递归建立左子树和右子树
- *root = (BinTree)malloc(sizeof(LNode));
- (*root)->chValue = ch;
- (*root)->leftMaxValue = 0;
- (*root)->rightMaxValue = 0;
- buildBinTree(&(*root)->pleft);
- buildBinTree(&(*root)->pright);
- }
- }
- //销毁二叉树,释放内存
- void destroyBinTree(BinTree *root)
- {
- if(*root != NULL) {
- destroyBinTree(&(*root)->pleft);
- destroyBinTree(&(*root)->pright);
- free(*root);
- *root = NULL;
- }
- }
- //前序遍历二叉树
- void preOrderTraverse(BinTree root)
- {
- if(root != NULL) {
- preOrderTraverse(root->pleft);
- printf("%c", root->chValue);
- preOrderTraverse(root->pright);
- }
- }
- int main() {
- BinTree root;
- buildBinTree(&root);
- preOrderTraverse(root);
- printf("\n");
- int maxLen = 0;
- findMaxLen(root, &maxLen);
- printf("maxLen = %d\n", maxLen);
- destroyBinTree(&root);
- }