赞
踩
想要对二叉树进行操作,我们得先构建一个二叉树
因此,这里的问题就是给定数据,如何将数据在逻辑结构上变成二叉树?
结构定义:
- typedef int BTDataType;
-
- typedef struct BinaryTreeNode
- {
- BTDataType val;
- struct BinaryTreeNode* left;
- struct BinaryTreeNode* right;
- }BTNode;
我们想构建上图的二叉树(#代表空),有两种方式
方法1:手动构建
- BTNode* CreateTreeNode(BTDataType x)
- {
- BTNode* newNode = (BTNode*)malloc(sizeof(BTNode));
- if (newNode == NULL)
- {
- perror("CreateTreeNode:malloc fail");
- exit(-1);
- }
- newNode->val = x;
- newNode->left = NULL;
- newNode->right = NULL;
-
- return newNode;
- }
-
- //方法1:手动构建
- BTNode* CreateBinaryTree(BTDataType* a)
- {
- BTNode* n1 = CreateTreeNode('a');
- BTNode* n2 = CreateTreeNode('b');
- BTNode* n3 = CreateTreeNode('c');
- BTNode* n4 = CreateTreeNode('d');
- BTNode* n5 = CreateTreeNode('e');
- BTNode* n6 = CreateTreeNode('f');
- BTNode* n7 = CreateTreeNode('g');
-
- n1->left = n2;
- n2->left = n3;
- n2->right = n4;
- n4->left = n5;
- n4->right = n6;
- n5->right = n7;
-
- return n1;
- }
很显然,这种方法不够高效,如果有上百个结点,每个结点都要我们手动去连接,效率实在太低;
我们的第二种方法是给你一个二叉树的前序/中序/后序遍历,用递归去构建二叉树;
当然了,在讲这种方法前,我们得先知道一棵树的前序/中序/后序遍历是什么
对于任意一颗二叉树,都有三种遍历,对应着不同的结点访问顺序
- 前序遍历:根->左子树->右子树
- 中序遍历:左子树->根->右子树
- 后序遍历:左子树->右子树->根
可以看到,三种遍历的本质是根结点的访问顺序
- //前序遍历
- void PrevOrder(BTNode* root)
- {
- if (root == NULL)
- {
- printf("NULL ");
- return;
- }
-
- printf("%c ", root->val);
- PrevOrder(root->left);
- PrevOrder(root->right);
- }
-
- //中序遍历
- void InOrder(BTNode* root)
- {
- if (root == NULL)
- {
- printf("NULL ");
- return;
- }
-
- InOrder(root->left);
- printf("%c ", root->val);
- InOrder(root->right);
- }
-
- //后序遍历
- void PostOrder(BTNode* root)
- {
- if (root == NULL)
- {
- printf("NULL ");
- return;
- }
-
- PostOrder(root->left);
- PostOrder(root->right);
- printf("%c ", root->val);
- }
讲完了二叉树的遍历,就可以试着用递归去构建二叉树了
方法2:递归构建
- //方法2:代码自动构建
- BTNode* CreateBinaryTree(BTDataType* a, int* pi)
- {
- if (a[(*pi)] == '#')
- {
- (*pi)++;
- return NULL;
- }
-
- BTNode* newNode = (BTNode*)malloc(sizeof(BTNode));
- if (newNode == NULL)
- {
- perror("CreateBinaryTree:malloc fail");
- exit(-1);
- }
- newNode->val = a[(*pi)++];
-
- newNode->left = CreateBinaryTree(a, pi);
- newNode->right = CreateBinaryTree(a, pi);
-
- return newNode;
- }
- //结点个数
- 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);
- }
- //第k层结点个数
- int BinaryTreeKSize(BTNode* root, int k)
- {
- if (root == NULL)
- return 0;
-
- if (k == 1)
- return 1;
-
- return BinaryTreeKSize(root->left, k - 1) + BinaryTreeKSize(root->right, k - 1);
- }
- //查找值为x的结点
- BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
- {
- if (root == NULL)
- return NULL;
-
- if (root->val == x)
- return root;
-
- BTNode* ret1 = BinaryTreeFind(root->left, x);
- if (ret1)
- return ret1;
-
- BTNode* ret2 = BinaryTreeFind(root->right, x);
- if (ret2)
- return ret2;
-
- return NULL;
- }
上面介绍的前序/中序/后序遍历属于深度优先遍历(DFS),准确点说前序遍历属于深度优先遍历;
而层序遍历属于广度优先遍历(BFS)
- 深度优先遍历:先访问完左子树在返回去访问右子树
- 广度优先遍历:先访问完一层,再去访问下一层
- //层序遍历
- void LevelOrder(BTNode* root)
- {
- Queue q;
- QueueInit(&q);
-
- if (root != NULL)
- QueuePush(&q, root);
-
- while (!QueueEmpty(&q))
- {
- QDataType front = QueueFront(&q);
- QueuePop(&q);
-
- if (front)
- {
- printf("%c ", front->val);
- QueuePush(&q, front->left);
- QueuePush(&q, front->right);
- }
- }
-
- QueueDestroy(&q);
- }
如果想打印完一层后换行,再打印下一层,该怎么实现?
- //层序遍历
- void LevelOrder(BTNode* root)
- {
- Queue q;
- QueueInit(&q);
-
- if (root != NULL)
- QueuePush(&q, root);
-
- int levelSize = 1;
-
- while (!QueueEmpty(&q))
- {
- while (levelSize--)
- {
- QDataType front = QueueFront(&q);
- QueuePop(&q);
-
- if (front)
- {
- printf("%c ", front->val);
- QueuePush(&q, front->left);
- QueuePush(&q, front->right);
- }
- }
- printf("\n");
- levelSize = QueueSize(&q);
- }
-
- QueueDestroy(&q);
- }
- //判断一颗二叉树是否为完全二叉树
- bool IsCompleteBinaryTree(BTNode* root)
- {
- Queue q;
- QueueInit(&q);
-
- if (root != NULL)
- QueuePush(&q, root);
-
- while (!QueueEmpty(&q))
- {
- QDataType front = QueueFront(&q);
- QueuePop(&q);
-
- if (front)
- {
- QueuePush(&q, front->left);
- QueuePush(&q, front->right);
- }
- else
- {
- break;
- }
- }
-
- while (!QueueEmpty(&q))
- {
- QDataType front = QueueFront(&q);
- QueuePop(&q);
-
- if (front != NULL)
- {
- QueueDestroy(&q);
- return false;
- }
- }
-
- QueueDestroy(&q);
- return true;
- }
- //二叉树的销毁
- void BinaryTreeDestroy(BTNode* root)
- {
- if (root == NULL)
- return;
-
- BinaryTreeDestroy(root->left);
- BinaryTreeDestroy(root->right);
- free(root);
- }
需要源码的小伙伴可以去我的Gitee主页查看
BInaryTree/BInaryTree · baiyahua/LeetCode - 码云 - 开源中国 (gitee.com)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。