扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
一般我们在学习数据结构的时候都会实现它最基本的增删查改方式,但是二叉树这个数据结构不太一般,增删查改没有什么意义,由于二叉树的相关遍历涉及到递归,我们先不学习创建二叉树,而是从遍历开始
在君山等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站设计、网站制作 网站设计制作按需定制制作,公司网站建设,企业网站建设,高端网站设计,成都全网营销推广,外贸网站建设,君山网站建设费用合理。简单的创建一个二叉树并不难,创建几个节点然后当作二叉树连起来即可:
typedef int BTDataType;
typedef struct BTNode
{
BTDataType data;
struct BTNode* left;
struct BTNode* right;
}BT;
BT* CreatTree()
{
BT* n1 = (BT*)malloc(sizeof(BT));
assert(n1);
BT* n2 = (BT*)malloc(sizeof(BT));
assert(n2);
BT* n3 = (BT*)malloc(sizeof(BT));
assert(n3);
BT* n4 = (BT*)malloc(sizeof(BT));
assert(n4);
BT* n5 = (BT*)malloc(sizeof(BT));
assert(n5);
BT* n6 = (BT*)malloc(sizeof(BT));
assert(n6);
n1->left = n2;
n1->right = n4;
n2->left = n3;
n2->right = NULL;
n3->left = NULL;
n3->right = NULL;
n4->left = n5;
n4->right = n6;
n5->left = NULL;
n5->right = NULL;
n6->left = NULL;
n6->right = NULL;
n1->data = 1;
n2->data = 2;
n3->data = 3;
n4->data = 4;
n5->data = 5;
n6->data = 6;
return n1;
}
逻辑结构如下图:
二叉树的遍历:前序遍历:
void preOrder(BT* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->data);
preOrder(root->left);
preOrder(root->right);
}
中序遍历:void MidOrder(BT* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
preOrder(root->left);
printf("%d ", root->data);
preOrder(root->right);
}
后序遍历://后序遍历
void leftOrder(BT* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
preOrder(root->left);
preOrder(root->right);
printf("%d ", root->data);
}
二叉树功能实现:二叉树节点个数:
int TreeSize(BT* root)
{
if (root == NULL)
return 0;
return TreeSize(root->left) + TreeSize(root->right) + 1;
}
二叉树叶子节点个数:int BinaryTreeLeafSize(BT* root)
{
if (root == NULL)
return 0;
if (root->left == NULL && root->right == NULL)
return 1;
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
二叉树高度:int BinaryTreeLeafHeight(BT* root)
{
if (root == NULL)
return 0;
int left = BinaryTreeLeafHeight(root->left) + 1;
int right = BinaryTreeLeafHeight(root->right) + 1;
if (left >right)
return left;
else
return right;
}
二叉树第k层节点个数:int BinaryTreeLevelKSize(BT* root, int k)
{
assert(k >0);
if (root == NULL)
return 0;
if (k == 1)
return 1;
return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}
二叉树查找值为x的节点:BT* BinaryTreeFind(BT* root, BTDataType x)
{
if (root == NULL)
return NULL;
if (root->data == x)
return root;
BT* leftret = BinaryTreeFind(root->left, x);
if (leftret)
return leftret;
BT* rightret = BinaryTreeFind(root->right, x);
if (rightret)
return rightret;
return NULL;
}
一些有关二叉树的题目
相信不少的读者在第一次接触到二叉树的时候对递归的把握并不深刻,在这里,其实递归的本质就是抛去了我们平常写代码注重全局的思想,改成了注重每次递归的时候应该做的事情,我个人没法详细表述的很好,在这里推荐一篇文章:三道题套路解决递归问题 | lyl's blog
单值二叉树:链接:力扣
if(root== NULL)
return true;
if(root->left && root->val != root ->left ->val )
return false;
if(root->right && root->val != root ->right ->val)
return false;
bool lefret = isUnivalTree(root ->left);
bool rightret = isUnivalTree(root ->right);
return lefret && rightret;
同遍历整个二叉树查找某个值的逻辑相同。
翻转二叉树:链接:力扣
思路:面对递归类型的题目,不应该直接专注于解决一整颗树上,而是每一步应该做什么,这题的主体每步的逻辑就是置换左右子树,那么我们不需要多想,直接交换左右子树,剩下的交给递归处理,不需要过度的照顾全局。
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL)
return NULL;
struct TreeNode* tmp = root->left;
root ->left = root->right;
invertTree(root->left);
invertTree(root->right);
return root;
}
};
相同的树:链接:力扣
思路:同上的翻转相同,我们只需要关注每一个节点对比的值是否符合要求即可,剩下的交给递归
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p == NULL && q == NULL)
return true;
if(p == NULL || q == NULL)
return false;
if(p->val != q->val)
return false;
bool leftret = isSameTree(p->left,q->left);
bool rightret = isSameTree(p->right,q->right);
return leftret && rightret ;
}
层序遍历:由于递归的栈帧消耗还是比较大的,所以用非递归的方法来遍历二叉树还是非常有必要的,借助队列的先进先出的特性可以很好的实现非递归遍历。
思路:二叉树无非就是跟和左子树右子树的问题,逻辑上来说,在我们在到达一个节点的时候接下来就是得到它的值或者是左子树右子树,那么我们就只需要先将根节点入队列,再将根的左子树右子树入队列,把根出队列后,再把其左右子树视作新根,再拆开成为左右子树,以达到层序遍历的效果。
void BinaryTreeLevelOrder(BTNode* root)// 层序遍历
{
Queue q;
QueueInit(&q);
if (root)//root不为空,放数据
QueuePush(&q,root);
while (!QueueEmpty(&q))//如果队列不为空,则循环
{
BTNode* front = QueueFront(&q);//拿队头数据
printf("%d ", front->data);
QueuePop(&q);
if (front->left)
QueuePush(&q, front->left);
if (front->right)
QueuePush(&q, front->right);
}
QueueDestroy(&q);
}
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流