链式二叉树
二叉树的遍历
定义和创建二叉树
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//定义二叉树节点
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
} BTNode;
//创建二叉树节点
BTNode* BuyNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL)
{
perror("BuyNode()::malloc fail");
return NULL;
}
node->data = x;
node->left = NULL;
node->right = NULL;
return node;
}
//随意创建一个二叉树
BTNode* CreatTree()
{
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;
}
遍历代码
//前序遍历
void PreOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
//后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
测试
int main()
{
BTNode* root = CreatTree();
PreOrder(root);
printf("\n");
InOrder(root);
printf("\n");
PostOrder(root);
printf("\n");
return 0;
}
结果
二叉树的节点个数
一般方法
int TreeSize(BTNode* root, int* psize)
{
if (root == NULL)
return;
(*psize)++;
TestSize(root->left, psize);
TestSize(root->right, psize);
}
int main()
{
BTNode* root = CreatTree();
PreOrder(root);
printf("\n");
InOrder(root);
printf("\n");
PostOrder(root);
printf("\n");
int size = 0;//使用前要置0
TreeSize(root, &size);
printf("%d\n", size);
return 0;
}
指挥打工人
int TreeSize(BTNode* root)
{
return root == NULL ? 0 ://若遇到空指针,则返回0
TreeSize(root->left)
+ TreeSize(root->right)
+ 1;//1是自身的节点
}
二叉树的深/高度
int TreeHeight(BTNode* root)
{
if (root == NULL)
return 0;
return TreeHeight(root->left) > TreeHeight(root->right)
? TreeHeight(root->left) + 1
: TreeHeight(root->right) + 1;
}
这样写可以完成计算深度的任务,但是不好,因为每次TreeHeight(root->left) 和 TreeHeight(root->right) 都会调用至少一遍,第一次是 ? 前的判断条件,第二次是要返回的值。
相当于一次比较知道谁大,但是不知道深度是多少,又要返回去计算,叶节点会被调用很多遍。
这样写显得臃肿。过于浪费算力资源,在大型场景跑不过。运算次数呈指数级增长。
改进后:
int TreeHeight(BTNode* root)
{
if (root == NULL)
return 0;
int left = TreeHeight(root->left);
int right = TreeHeight(root->right);
return left > right ? left + 1 : right + 1;
}
根的第k层个数
公式:
根的第k层个数 = 左子树的第k-1层个数 + 右子树的第k层个数
int TreeKLevel(BTNode* root, int k)
{
assert(k > 0);
if (root == NULL)
return 0;
if (k == 1)
return 1;
return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);
}