赞
踩
其他数据结构不同,二叉树的增删查改接口实现的意义不大(后续搜索树的增删查改才有意义)。普通初阶二叉树更重要的是学习控制结构,为后续的AVL树、红黑树等高级数据结构打下基础。同时大部分OJ题也出在此处。
所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。
按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:
【代码思路】:
代码:
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 PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
前序遍历递归图解:
上述三种遍历结果:
层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
【代码思路】:(核心思想:上一层出时带下一层进队列,即根节点出栈时,根节点的孩子节点入栈)
栈相关代码自行查看:栈和队列代码实现
代码:
void LevelOrder(BTNode* root) { Queue q; QueueInit(&q); if (root) QueuePush(&q, root); while (!QueueEmpty(&q)) { BTNode* front = QueueFront(&q); QueuePop(&q); printf("%d ", front->data); if(front->left) QueuePush(&q, front->left); if (front->right) QueuePush(&q, front->right); } printf("\n"); QueueDestroy(&q); }
【代码思路】:
代码:
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);
}
【代码思路】:
代码:
int BinaryTreeLevelKSize(BTNode* 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); }
【代码思路】:
代码:
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; }
【代码思路】:
代码:
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;
}
Tips: 构建二叉树的方式有很多, 这里我们通过前序遍组"ABD##E#H##CF##G##"构建二叉树。(‘#’表示空树)
【代码思路】:
代码:
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("malloc fail"); exit(-1); } Node->data = x; Node->left = NULL; Node->right = NULL; return Node; } //先序创建二叉树 BTNode* createrroot(char* a, int* pi) { if (a[*pi] == '#') { (*pi)++; return NULL; } BTNode* root = BuyNode(a[*pi]); (*pi)++; root->left = createrroot(a, pi); root->right = createrroot(a, pi); return root; }
【代码思路】:
代码:
void BinaryTreeDestroy(BTNode* root)
{
if (root == NULL)
return;
BinaryTreeDestory(root->left);
BinaryTreeDestory(root->right);
free(root);
}
(博主数据结构初阶是用C语言来实现的,所以此处直接栈代码从博主代码仓库中拷贝过来的,读者可以用其他语言来实现,大同小异)
【代码思路】:
栈相关代码自行查看:栈和队列代码实现
代码:
int BinaryTreeComplete(BTNode* root) { Que q; QueueInit(&q); if (root) QueuePush(&q, root); while (!QueueEmpty(&q)) { BTNode* front = QueueFront(&q); QueuePop(&q); //遇空就跳过 if (front==NULL) { break; } QueuePush(&q, root->left); QueuePush(&q, root->right); } //检查后续节点是否有非空 //有非空就不是完全二叉树 while (!QueueEmpty(&q)) { BTNode* front = QueueFront(&q); QueuePop(&q); if (front) { QueueDestroy(&q); return false; } } QueueDestroy(&q); return true; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。