目录
需要我前面堆的基础,递归要熟
二叉树的创建
这个就简单了,自己手动创建,后面再讲更好的方式创建
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(int k)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
if (newnode == NULL)
{
perror("malloc fail");
return NULL;
}
newnode->data = k;
newnode->left = NULL;
newnode->right = NULL;
}
BTNode* CreatBinaryTree()
{
BTNode* node1 = BuyNode(1);
BTNode* node2 = BuyNode(2);
BTNode* node3 = BuyNode(3);
BTNode* node4 = BuyNode(4);
BTNode* node5 = BuyNode(5);
BTNode* node6 = BuyNode(6);
node1->left = node2;
node1->right = node4;
node2->left = node3;
node4->left = node5;
node4->right = node6;
return node1;
}
二叉树的遍历
前序遍历
根结点 -> 左子树 -> 右子树
这个前序遍历是(N代表空): 1 2 3 N N N 4 5 N N 6 N N
前序遍历的实现
void PreOrder(BTNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
printf("%d ",root->data);
PreOrder(root->left);
PreOrder(root->right);
}
按序号看
中序遍历
同理
左子树-> 根节点 -> 右子树
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
按上面画图就好理解了
后序遍历
左子树 -> 右子树 -> 根节点
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
层序遍历
用什么遍历呢?
用队列好,上一层出时带它的左右孩子
void LevelOrdrt(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
{
return;
}
QueuePush(&q, root);//这里插入的是节点指针
while (!QueueEmpty(&q))
{
BTNode* tem = QueueFront(&q);//这里的到的是节点指针
QueuePop(&q);
printf("%d ", tem->data);
if(tem->left)
{
QueuePush(&q, tem->left);
}
if(tem->right)
{
QueuePush(&q,tem->right);
}
}
printf("\n");
}
二叉树的节点个数
思路:从根节点出发,他的左子树的节点个数+它的右子树的节点个数+自己
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
二叉树叶子节点个数
思路:什么是叶子节点,他的左右孩子都是空,从头节点出发他的左子树的叶节点+右子树的叶节点
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
二叉树的高度
思路:从根节点出发,看他的左子树的高度和右子树的高度哪个大就要哪个,大的+1
int BinaryTreeHeight(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int leftheight = BinaryTreeHeight(root->left);
int rightheight = BinaryTreeHeight(root->right);
return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
}
自己画递归图理解啦
二叉树第k层节点个数
int BinaryTreeLevelkSize(BTNode* root,int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelkSize(root->left, k - 1) + BinaryTreeLevelkSize(root->right, k - 1);
}
自己画递归图理解啦
二叉树中寻找元素
思路:从根节点出发,先找左子树,再找右子树找到就返回
BTNode* BinaryTreeFind(BTNode* root, int x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode* tem1=BinaryTreeFind(root->left, x);
if(tem1)
return tem1;
BTNode* tem2 = BinaryTreeFind(root->right, x);
if (tem2)
return tem2;
return NULL;
}
错误写法:
1.
//错的
BTNode* BinaryTreeFind1(BTNode* root, int x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
return BinaryTreeFind1(root->left, x) || BinaryTreeFind1(root->right, x);
/*不能这样返回,是真就返回1,假就是0,不能返回地址*/
}
2.
BTNode* BinaryTreeFind(BTNode* root, int x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BinaryTreeFind(root->left, x);//没有接收返回值
BinaryTreeFind(root->right, x);
}
递归要小心返回值,返回值是返回给上一层函数
二叉树的的销毁
思路:按照后序遍历销毁
void BinaryTreeDestory(BTNode* root)
{
if (root == NULL)
{
return;
}
BinaryTreeDestory(root->left);
BinaryTreeDestory(root->right);
free(root);
}
自己画递归图理解啦
总结:
- 二叉树是很多子树的集合,当你去写关于二叉树的代码时,可以先想象成简单的二叉树(两层的二叉树),从根节点出发,分为左右子树去想,写出思路,然后再添加子树进去,就会有递归了
- 递归一定要关注返回值,函数返回值是返回到原来的函数的,不是自己能返回到最外面的