EB4-二叉树最大值结点查找
代码实现
| C |
|---|
| /**
* 在二叉树中查找值最大的结点
* @param p 当前遍历的二叉树结点
* @param m 指向最大值结点的指针的地址
*/
void findMaxNode(BiTree p, BiTree *m) {
// 如果当前结点不为空,则继续遍历
if (p != NULL) {
// 如果m指向的结点为空,或者当前结点的值大于m指向结点的值
// 则更新m指向当前结点# 二叉树最大值结点查找函数分析
if ((*m) == NULL || p->data > (*m)->data) {
*m = p; // 更新最大值结点指针
}
// 递归遍历左子树
findMaxNode(p->lchild, m);
// 递归遍历右子树
findMaxNode(p->rchild, m);
}
}
|
代码执行流程图解
| Text Only |
|---|
| 5
/ \
3 8
/ \ \
2 4 9
/
1
执行过程:
1. 访问根节点5,m=NULL,更新m指向5
2. 递归访问左子树(3)
- 访问3,3>5? 否,m仍指向5
- 递归访问2,2>5? 否,m仍指向5
- 递归访问1,1>5? 否,m仍指向5
3. 递归访问右子树(8)
- 访问8,8>5? 是,更新m指向8
- 递归访问9,9>8? 是,更新m指向9
最终:m指向值为9的结点
|
复杂度分析
时间复杂度:O(N)
- 分析过程:
- 函数需要遍历二叉树的每一个结点 exactly 一次
- 对于每个结点,只进行常数时间的比较操作
- 设二叉树有N个结点,则总时间复杂度为O(N)
空间复杂度:O(N)
- 分析过程:
- 主要消耗在递归调用栈的空间
- 最坏情况下(完全不平衡的二叉树,退化为链表),递归深度为N,空间复杂度为O(N)
- 最好情况下(完全平衡的二叉树),递归深度为logN,空间复杂度为O(logN)
- 综合考虑,空间复杂度为O(N)
相关知识点延伸
1. 二叉树遍历方式
| C |
|---|
| // 前序遍历(根-左-右)- 本题使用的方式
void preorder(BiTree p) {
if (p != NULL) {
visit(p); // 处理当前结点
preorder(p->lchild); // 遍历左子树
preorder(p->rchild); // 遍历右子树
}
}
// 中序遍历(左-根-右)
void inorder(BiTree p) {
if (p != NULL) {
inorder(p->lchild);
visit(p);
inorder(p->rchild);
}
}
// 后序遍历(左-右-根)
void postorder(BiTree p) {
if (p != NULL) {
postorder(p->lchild);
postorder(p->rchild);
visit(p);
}
}
|
2. 迭代实现方式(使用栈)
| C |
|---|
| /**
* 迭代方式查找二叉树最大值结点
*/
void findMaxNodeIterative(BiTree root, BiTree *m) {
if (root == NULL) return;
Stack s; // 假设有栈结构
initStack(&s);
push(&s, root);
*m = root;
while (!isEmpty(&s)) {
BiTree p = pop(&s);
// 更新最大值结点
if (p->data > (*m)->data) {
*m = p;
}
// 将子结点入栈
if (p->rchild != NULL) push(&s, p->rchild);
if (p->lchild != NULL) push(&s, p->lchild);
}
}
|
3. 层序遍历实现(使用队列)
| C |
|---|
| /**
* 层序遍历方式查找最大值结点
*/
void findMaxNodeLevelOrder(BiTree root, BiTree *m) {
if (root == NULL) return;
Queue q; // 假设有队列结构
initQueue(&q);
enqueue(&q, root);
*m = root;
while (!isEmpty(&q)) {
BiTree p = dequeue(&q);
// 更新最大值结点
if (p->data > (*m)->data) {
*m = p;
}
// 将子结点入队
if (p->lchild != NULL) enqueue(&q, p->lchild);
if (p->rchild != NULL) enqueue(&q, p->rchild);
}
}
|
关键要点总结
- 指针的指针使用:
BiTree *m 用于在递归过程中保持对最大结点引用的更新
- 递归遍历:采用前序遍历确保每个结点都被访问到
- 比较逻辑:需要处理初始情况(
*m == NULL)和一般情况
- 完整遍历:必须访问所有结点才能确定最大值
这个算法虽然简单,但体现了二叉树遍历的基本思想和指针操作的技巧,在数据结构算法中具有代表性。