算法与数据结构基础(三)之二叉树
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