树(二叉树(创建,打印,删除))
定义:除了根节点之外,每个结点都有一个父节点,除了叶子节点外所有的节点都有一个或者多个子节点。二叉树:每个节点最多有两个叶子节点
遍历:按照某个顺序访问树中的所有节点。
三种常见的遍历:前序遍历,中序遍历,后续遍历(可以用递归和循环两种方式实现)
可实现的题目:二叉树的深度,树的子结构,二叉树的后续遍历。从上到下遍历二叉树(宽度优先遍历)。
二查搜索树:左子结点总是小于等于根节点,而右子节点总是大于等于根节点。找到一个节点的平均时间为O(logn)
二叉树特例:堆和红黑二叉树堆:最大堆和最小堆。可以解决(快速找最大值和最小值问题)
红黑树:将树中的节点定义为红、黑两种颜色,通过规则确保从根节点到叶子节点的最长路径不超过最短路径的两倍。在C++ 中的STL(Standard Template libary(标准模板库),set,multiset,map,multimap等数据结构都是基于红黑树实现的。)
重建二叉树
题目:输入某个二叉树的前序遍历和中序遍历的结果,重建该二叉树,假设输入前序和中序遍历的结果中没有重复的数字。例如:输出得 前序遍历为{1,2,4,7,3,5,6,8}和中序遍历{4,7,2,1,5,3,8,6},重建二叉树。思路:
1.创建二叉树,返回值为BinaryTreeNode *,BinaryTreeNode* construct(int* preorder,int* inorder,int length)(如果前序遍历和中序遍历的头指针都不空,及length大于0,则调用函数BinaryTreeNode *ConstructCore(int*startPreorder,int*endPreorder,int*startInorder,int*endInorder)(首先将前序遍历的第一个值赋值给rootValue,初始化 根节点,if(startPreorder==endPreorder){if(startInorder==endInorder&&*startPreorder==*startInorder) return root;else 抛空异常。) 据中序遍历找到根节点。定义一个行动指针指p向中序遍历的头结点。当满足p<=endInorder时,找到根节点(root),分别求出左、右子树的长度leftLength和rightLength,当leftLength和rightLength不为零时,分别创建左右子树。root->left=调用ConstructCore函数,root->right=调用ConstructCore函数。2.打印二叉树。无返回值。首先创建要打印一个节点的函数void printTreeNode(BinaryTreeNode* pNode)(当pNode不为空时,打印pNode的值,如果pNode->left为空,打印pNode->left->value,右指针同左指针一样操作。else 抛空。),然后再创建一个函数,返回值为空。void PrintTree(BinaryTreeNode *root){如果根节点不 为空打印根节点的值,左指针不为空,递归打印左子树。右指针同理。}。
3.删除二叉树。无返回值。函数void DeleteNode(BinaryTreeNode* pRoot){如果pRoot不为空,则将左右指针分别赋值给一个新的指针,然后删除pRoot,并且置空。递归删除左右子树。}
#include <stdio.h>
#include <iostream>
using namespace std;
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
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(startInorder==endInorder&&*startPreorder==*startInorder)
{
return root;
}
else
throw std::exception("Invalid put!");
}
//通过中序遍历序列找到根节点
int* rootInorder=startInorder;
while(rootInorder<=endInorder&&*rootInorder!=rootValue)
{
++rootInorder;
}
if(rootInorder==endInorder&&*rootInorder!=rootValue)
{
throw std::exception("Invalid put");
}
int leftLength=rootInorder-startInorder;
int rightLength=endInorder-rootInorder;
int* leftPreorderEnd=startPreorder+leftLength;
if(leftLength>0)
{
//递归构建左子树
root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
}
if(rightLength>0)
{
//递归构建右子树
root->m_pRight=ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
}
return root;
}
BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
if(preorder==NULL||inorder==NULL||length<=0)
{
throw std::exception("Invalid put!");
}
return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
}
void PrintTreeNode(BinaryTreeNode* pNode)
{
if(pNode != NULL)
{
printf("value of this node is: %d\n", pNode->m_nValue);
if(pNode->m_pLeft != NULL)
printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
else
printf("left child is null.\n");
if(pNode->m_pRight != NULL)
printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
else
printf("right child is null.\n");
}
else
{
printf("this node is null.\n");
}
printf("\n");
}
//递归打印左右子树
void PrintTree(BinaryTreeNode* pRoot)
{
PrintTreeNode(pRoot);
if(pRoot != NULL)
{
if(pRoot->m_pLeft != NULL)
PrintTree(pRoot->m_pLeft);
if(pRoot->m_pRight != NULL)
PrintTree(pRoot->m_pRight);
}
}
//递归删除左右子树
void DestroyTree(BinaryTreeNode* pRoot)
{
if(pRoot != NULL)
{
BinaryTreeNode* pLeft = pRoot->m_pLeft;
BinaryTreeNode* pRight = pRoot->m_pRight;
delete pRoot;
pRoot = NULL;
DestroyTree(pLeft);
DestroyTree(pRight);
}
}
void main()
{
const int length = 8;
int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};
int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};
BinaryTreeNode *root = Construct(preorder, inorder, length);
PrintTree(root);
DestroyTree(root);
}