学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。 访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
任何二叉树都能分成三个结构:
二叉树的四种遍历结构:
递归调用自己建立栈帧
执行指令,建立栈帧,局部变量就存在栈帧里面的
二叉树复杂的原因是它是双路递归
分治: (分而治之)
把复杂的问题,分成更小规模的子问题,子问题再分成更小规模的子问题。。。
直到子问题不可再分割,直接能出结果。
typedef int BTDataType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
BTDataType data;
}BTNode;
//创建新结点
BTNode* BuyBTNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL)
{
exit(-1);
}
node->data = x;
node->left = node->right = NULL;
return node;
}
//创建二叉树
BTNode* CreatBinaryTree()
{
BTNode* node1 = BuyBTNode(1);
BTNode* node2 = BuyBTNode(2);
BTNode* node3 = BuyBTNode(3);
BTNode* node4 = BuyBTNode(4);
BTNode* node5 = BuyBTNode(5);
BTNode* node6 = BuyBTNode(6);
node1->left = node2;
node1->right = node4;
node2->left = node3;
node4->left = node5;
node4->right = node6;
return node1;
}
//前序遍历
void PrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->data);
PrevOrder(root->left);
PrevOrder(root->right);
}
中序遍历和后序遍历与前序遍历极其相似,根据其特定的遍历顺序依次递归即可。
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
//后续遍历
void BackOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
BackOrder(root->left);
BackOrder(root->right);
printf("%d ", root->data);
}
计算二叉树中结点的个数
//树中结点的个数 - 设置全局变量
int count = 0;
void BTreeSize(BTNode* root)
{
if (root == NULL)
{
return;
}
count++;
BTreeSize(root->left);
BTreeSize(root->right);
}
//最安全的方式 - 传地址
//思想: 遍历 + 计数
void BTreeSize(BTNode* root, int* pCount)
{
if (root == NULL)
{
return;
}
(*pCount)++;
BTreeSize(root->left, pCount);
BTreeSize(root->right, pCount);
}
新思路:用递归的分治的思想
//结点数目 - 新思路
int BTreeSize(BTNode* root)
{
return root == NULL ? 0 : BTreeSize(root->left)
+ BTreeSize(root->right) + 1;
}
//计算叶子结点的个数
int BTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);
}
分治的思想:
//第k层的结点的个数, k >= 1
int BTreeKLevelSize(BTNode* root, int k)
{
assert(k >= 1);
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BTreeKLevelSize(root->left, k - 1) +
+BTreeKLevelSize(root->right, k - 1);
分治的思想:
//求二叉树的深度(高度)
int BTreeDepth(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int leftDepth = BTreeDepth(root->left);
int rightDepth = BTreeDepth(root->right);
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
分治的思想:
递归展开图如下:
//查找二叉树值为x的结点
BTNode* BTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode* ret1 = BTreeFind(root->left, x);
if (ret1)
{
return ret1;
}
BTNode* ret2 = BTreeFind(root->right, x);
if (ret2)
{
return ret2;
}
return NULL;
}
//二叉树的销毁 - 后续方式销毁即可
void BTreeDestroy(BTNode* root)
{
if (root == NULL)
{
return;
}
BTreeDestroy(root->left);
BTreeDestroy(root->right);
free(root);
}
int main()
{
BTNode* tree = CreatBinaryTree();
PrevOrder(tree);
printf("\n");
InOrder(tree);
printf("\n");
BackOrder(tree);
printf("\n");
/*count = 0;
BTreeSize(tree);
printf("size:%d\n",count);
count = 0;
BTreeSize(tree);
printf("size:%d\n", count);*/
/*int count1 = 0;
BTreeSize(tree, &count1);
printf("size:%d\n", count1);
int count2 = 0;
BTreeSize(tree, &count2);
printf("size:%d\n", count2);*/
printf("size:%d\n", BTreeSize(tree));
printf("Leaf size:%d\n", BTreeLeafSize(tree));
printf("Depth size:%d\n", BTreeDepth(tree));
printf("BTree 3 level size:%d\n", BTreeKLevelSize(tree, 3));
for (int i = 1; i <= 7; i++)
{
printf("Find: %d,%p\n", i, BTreeFind(tree, i));
}
return 0;
}