算法与数据结构基础(三)之二叉树

0、二叉树

(1)定义

二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

(2) 二叉树特点

由二叉树定义以及图示分析得出二叉树有以下特点:
1)每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点。
2)左子树和右子树是有顺序的,次序不能任意颠倒。
3)即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。

(3)二叉树性质

1)在二叉树的第i层上最多有2i-1 个节点 。(i>=1)
2)二叉树中如果深度为k,那么最多有2k-1个节点。(k>=1)
3)n0=n2+1 n0表示度数为0的节点数,n2表示度数为2的节点数。
4)在完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]是向下取整。
5)若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点有如下特性:

(1) 若 i=1,则该结点是二叉树的根,无双亲, 否则,编号为 [i/2] 的结点为其双亲结点;
(2) 若 2i>n,则该结点无左孩子, 否则,编号为 2i 的结点为其左孩子结点;
(3) 若 2i+1>n,则该结点无右孩子结点, 否则,编号为2i+1 的结点为其右孩子结点。

1 、二叉树节点

struct BinaryTreeNode
{
	int                    m_nValue;
	BinaryTreeNode*        m_pLeft;
	BinaryTreeNode*        m_pRight;
};

2、创建二叉树节点

BinaryTreeNode* CreateBinaryTreeNode(int value)
{
	BinaryTreeNode* pNode = new BinaryTreeNode();
	pNode->m_nValue = value;
	pNode->m_pLeft = nullptr;
	pNode->m_pRight = nullptr;

	return pNode;
}

3、连接树节点

void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
{
	if (pParent != nullptr)
	{
		pParent->m_pLeft = pLeft;
		pParent->m_pRight = pRight;
	}
}

4、打印树节点

void PrintTreeNode(const BinaryTreeNode* pNode)
{
	if (pNode != nullptr)
	{
		printf("value of this node is: %d\n", pNode->m_nValue);

		if (pNode->m_pLeft != nullptr)
			printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
		else
			printf("left child is nullptr.\n");

		if (pNode->m_pRight != nullptr)
			printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
		else
			printf("right child is nullptr.\n");
	}
	else
	{
		printf("this node is nullptr.\n");
	}

	printf("\n");
}

5、打印二叉树

void PrintTree(const BinaryTreeNode* pRoot)
{
	PrintTreeNode(pRoot);

	if (pRoot != nullptr)
	{
		if (pRoot->m_pLeft != nullptr)
			PrintTree(pRoot->m_pLeft);

		if (pRoot->m_pRight != nullptr)
			PrintTree(pRoot->m_pRight);
	}
}

6、销毁二叉树

void DestroyTree(BinaryTreeNode* pRoot)
{
	if (pRoot != nullptr)
	{
		BinaryTreeNode* pLeft = pRoot->m_pLeft;
		BinaryTreeNode* pRight = pRoot->m_pRight;

		delete pRoot;
		pRoot = nullptr;

		DestroyTree(pLeft);
		DestroyTree(pRight);
	}
}

7、求二叉树的深度

int TreeDepth(const BinaryTreeNode* pRoot)
{
	if (pRoot == nullptr)
		return 0;

	int nLeft = TreeDepth(pRoot->m_pLeft);
	int nRight = TreeDepth(pRoot->m_pRight);

	return (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);
}

已知中序遍历、后序遍历、求前序遍历。

#include<iostream>
#include<string>

using namespace std;

string s1, s2;
void print(int l1, int r1, int l2, int r2)
{
	int k = -1;
	for (int i = l1; i < r1; i++)
	{
		if (s1[i] == s2[r2 - 1])
		{
			cout << s1[i];
			k = i;
			break;
		}
	}
	//cout<<"k "<<k<<endl;
	if (k > l1)
	{
		//cout<<"进入左"<<endl;
		print(l1, k, l2, k - l1 + l2);
	}
	if (r1 > k + 1)
	{
		//cout<<"进入右"<<endl;
		print(k + 1, r1, k - l1 + l2, r2 - 1);
	}

}
int main()
{
	cin >> s1 >> s2;
	print(0, s1.length(), 0, s2.length());
	return 0;
}

已知前序遍历、中序遍历,求后序遍历。


#include <iostream>
#include <vector>
using   namespace   std;

struct  TreeNode
{
	int val;
	TreeNode   *left;
	TreeNode    *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};


TreeNode *  reConstructBinaryTree(vector<int> pre, vector<int> in)
{
	if (pre.size() == NULL || in.size() == NULL)
		return NULL;
	TreeNode *root = new TreeNode(pre[0]);   //前序遍历:根左右,,第一个为根
	int i;
	for (i = 0; i < in.size() && in[i] != pre[0]; i++);   //找到中序遍历中根结点的位置i.
	vector<int> pre_left, in_left, pre_right, in_right;
	int pre_i = 1;
	for (int j = 0; j < in.size(); j++)
	{
		if (j < i)
		{
			in_left.push_back(in[j]);
			pre_left.push_back(pre[pre_i]);
			pre_i++;
		}
		else if (j > i)
		{
			in_right.push_back(in[j]);
			pre_right.push_back(pre[pre_i]);
			pre_i++;
		}
	}
	root->left = reConstructBinaryTree(pre_left, in_left);
	root->right = reConstructBinaryTree(pre_right, in_right);
	return root;
}

void Print(vector<int> &vec)
{
	int num = vec.size();
	if (vec.size() == 0)
		return;
	else
	{
		for (int i = 0; i < vec.size(); i++)
		{
			cout << vec[i] << "  ";
		}
		cout << endl;
	}
}

void  PostOrder(TreeNode* root)  //后续遍历
{

	if (root == NULL)
		return;
	else
	{
		PostOrder(root->left);
		PostOrder(root->right);
		cout << root->val << "  ";
	}
	return;
}


int main()
{
	vector<int> pre = { 1,2,4,7,3,5,6,8 };
	vector<int>  in = { 4,7,2,1,5,3,8,6 };
	cout << "前序遍历为:" << endl;
	Print(pre);
	cout << "中序遍历为:" << endl;
	Print(in);

	TreeNode* root = reConstructBinaryTree(pre, in);
	cout << "后序遍历为:" << endl;
	PostOrder(root);
	system("pause");

	return 0;
}

参考文献

参考文章:https://www.jianshu.com/p/bf73c8d50dc2

代码参考:https://github.com/zhulintao/CodingInterviewChinese2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知行SUN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值