数据结构——二叉树面试题(1)

#pragma once

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

typedef char DataType;

typedef struct BTreeNode {
	struct BTreeNode *pLeft;
	struct BTreeNode *pRight;

	DataType data;
}	BTreeNode;


BTreeNode * CreateNode(DataType data)
{
	BTreeNode *pNode = (BTreeNode *)malloc(sizeof(BTreeNode));
	assert(pNode != NULL);
	pNode->pLeft = pNode->pRight = NULL;
	pNode->data = data;

	return pNode;
}

BTreeNode * CreateTree(DataType pre[], int size, int *index)
{
	// 判断条件
	// 1 越界;2 == #
	if (*index >= size) {
		return NULL;
	}

	if (pre[*index] == '#') {
		(*index)++;
		return NULL;
	}

	BTreeNode *pRoot = CreateNode(pre[*index]);
	(*index)++;

	pRoot->pLeft = CreateTree(pre, size, index);
	pRoot->pRight = CreateTree(pre, size, index);

	return pRoot;
}

int GetHeightR(BTreeNode *pRoot)
{
	if (pRoot == NULL) {
		return 0;
	}

	int left = GetHeightR(pRoot->pLeft);
	int right = GetHeightR(pRoot->pRight);

	return (left > right ? left : right) + 1;
}

void GetHeight(BTreeNode *pRoot, int *pHeight)
{
	if (pRoot == NULL) {
		*pHeight = 0;
		return;
	}

	int left, right;
	GetHeight(pRoot->pLeft, &left);
	GetHeight(pRoot->pRight, &right);

	*pHeight = (left > right ? left : right) + 1;
}

int MAX(int a, int b, int c)
{
	if (a >= b && a >= c) {
		return a;
	}

	if (b >= a && b >= c) {
		return b;
	}

	return c;
}

int 找最远距离(BTreeNode *pRoot)
{
	if (pRoot == NULL) {
		return 0;
	}

	int leftHeight = GetHeightR(pRoot->pLeft);
	int rightHeight = GetHeightR(pRoot->pRight);
	int rootPath = leftHeight + rightHeight;
	int leftPath = 找最远距离(pRoot->pLeft);
	int rightPath = 找最远距离(pRoot->pRight);

	return MAX(rootPath, leftPath, rightPath);
}


int 找最远距离优化版(BTreeNode *pRoot, int *pHeight)
{
	if (pRoot == NULL) {
		*pHeight = 0;
		return 0;
	}

	int leftHeight, rightHeight;
	int leftPath = 找最远距离优化版(pRoot->pLeft, &leftHeight);
	int rightPath = 找最远距离优化版(pRoot->pRight, &rightHeight);
	int rootPath = leftHeight + rightHeight;
	*pHeight = (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;

	return MAX(rootPath, leftPath, rightPath);
}

void Mirror(BTreeNode *pRoot)
{
	if (pRoot == NULL) {
		return;
	}

	// 可加可不加(加了效率更好)
	if (pRoot->pLeft == NULL && pRoot->pRight == NULL) {
		return;
	}

	BTreeNode *pLeft = pRoot->pLeft;
	pRoot->pLeft = pRoot->pRight;
	pRoot->pRight = pLeft;

	Mirror(pRoot->pLeft);
	Mirror(pRoot->pRight);
}

int IsBalance(BTreeNode *pRoot)
{
	if (pRoot == NULL) {
		return 1;
	}
	int left = IsBalance(pRoot->pLeft);
	if (left == 0) {
		// 左子树不平衡
		return 0;
	}
	int right = IsBalance(pRoot->pRight);
	if (right == 0) {
		// 右子树不平衡
		return 0;
	}
	// 左右子树都平衡
	int leftH = GetHeightR(pRoot->pLeft);
	int rightH = GetHeightR(pRoot->pRight);

	if (leftH - rightH >= -1 && leftH - rightH <= 1) {
		return 1;
	}
	else {
		return 0;
	}
}

BTreeNode * Find(BTreeNode *pRoot, BTreeNode *node)
{
	if (pRoot == NULL) {
		return NULL;
	}

	if (pRoot == node) {
		return pRoot;
	}

	BTreeNode *pFound = Find(pRoot->pLeft, node);
	if (pFound != NULL) {
		return pFound;
	}

	return Find(pRoot->pRight, node);
}

BTreeNode * 找最近公共祖先(BTreeNode *pRoot, BTreeNode *n1, BTreeNode *n2)
{
	// 在左子树中找 n1
	BTreeNode *pN1LeftFound = Find(pRoot->pLeft, n1);
	// 在左子树中找 n2
	BTreeNode *pN2LeftFound = Find(pRoot->pLeft, n2);
	// 在右子树中找 n1
	BTreeNode *pN1RightFound = Find(pRoot->pRight, n1);
	// 在右子树中找 n2
	BTreeNode *pN2RightFound = Find(pRoot->pRight, n2);

	/* 四种情况
	1. n1 和 n2 分别在一棵子树中
	2. n1 和 n2 不在一棵子树中
	3. n1 或者 n2 一个是根(pRoot),另一个在一棵子树中
	4. n1 或者 n2 有一个没找到
	*/

	if (pN1LeftFound != NULL && pN2LeftFound != NULL) {
		// n1 和 n2 都在左子树中
		return 找最近公共祖先(pRoot->pLeft, n1, n2);
	}

	if (pN1RightFound != NULL && pN2RightFound != NULL) {
		// n1 和 n2 都在右子树中
		return 找最近公共祖先(pRoot->pRight, n1, n2);
	}

	if (pN1LeftFound != NULL && pN2RightFound != NULL) {
		// n1 在左,n2 在右
		return pRoot;
	}

	if (pN2LeftFound != NULL && pN1RightFound != NULL) {
		// n1 在右,n2 在左
		return pRoot;
	}

	if (n1 == pRoot && (pN2LeftFound || pN2RightFound)) {
		// n1 是根,n2 在子树中
		return pRoot;
	}

	if (n2 == pRoot && (pN1LeftFound || pN1RightFound)) {
		// n2 是根,n1 在子树中
		return pRoot;
	}

	return NULL;
}


BTreeNode * CreateTreeByPreOrderAndInOrder(
	char preOrder[], int preOrderSize,
	char inOrder[], int inOrderSize)
{
	if (preOrderSize <= 0) {
		return NULL;
	}

	char rootChar = preOrder[0];	// 这里越界了么?
	int i;
	for (i = 0; i < inOrderSize; i++) {
		if (inOrder[i] == rootChar) {
			break;
		}
	}

	if (i == inOrderSize) {
		// 没找到,出错
		assert(0);
	}

	BTreeNode *pRoot = CreateNode(rootChar);
	pRoot->pLeft = CreateTreeByPreOrderAndInOrder(
		preOrder + 1, i,
		inOrder, i);
	pRoot->pRight = CreateTreeByPreOrderAndInOrder(
		preOrder + 1 + i, preOrderSize - i - 1,
		inOrder + 1 + i, inOrderSize - i - 1);

	return pRoot;
}



void Test()
{
	char *preOrder = "ABDCEF";
	char *inOrder = "DBAECF";
	BTreeNode *pRoot = CreateTreeByPreOrderAndInOrder(
		preOrder, 6, inOrder, 6);

	printf("Tree\n");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值