对于进阶的解法我给出了超级详细的注释,跟着模拟再顺几遍差不多就能理解透彻了
Node* connect(Node* root) {
// 法一、BFS层序遍历 + 队列
// queue<Node*> que;
// if (root != nullptr) que.push(root);
// while (!que.empty()) {//遍历每一层
// int size = que.size();
// while (size--) {
// Node* p = que.front();
// que.pop();
// if (size > 0) p->next = que.front();//除了最右结点
// if (p->left) que.push(p->left);
// if (p->right) que.push(p->right);
// }
// }
// return root;
// 进阶O(1)、利用next指针
Node* start = root;//每层开始遍历的结点
while(start){
//外层循环(遍历每一层)结束条件是?———start==nullptr,也就是该层没有有子节点的结点了也就是全部遍历完成
while(start && start->left == nullptr && start->right == nullptr) start = start->next;//start再更新为该层第一个存在子结点的结点,从第一个存在子节点的结点开始遍历,给下一层做连接
//退出循环时start有两种情况:1、存在子节点;2、start为空==>说明该层结点都不存在子节点,则该树的连接已全部完成
if (start == nullptr) return root;
Node* linkto = nullptr;//linkto是要去做连接的的结点(每层开始遍历前都要初始化一下)
//开始遍历start这层结点(cur指向正在遍历的结点),给下一层结点做连接
for (Node* cur = start; cur != nullptr; cur = cur->next) {
//内层循环(遍历一层的结点)结束条件是?———cur==nullptr
//该层连接一旦一开始之后linkto就不为空了
if(cur->left) {//若cur存在左子
if(linkto != nullptr) linkto->next = cur->left;
linkto = cur->left;//则其左子就是下一步要去做连接的的结点
}
if(cur->right) {//若cur存在右子
if(linkto != nullptr) linkto->next = cur->right;
linkto = cur->right;//更新要去做连接的的结点linkto
}
// 或写成:(但是没有上面的简洁)
// if (linkto != nullptr) {
// if (cur->left) {
// linkto->next = cur->left;
// linkto = cur->left;
// }
// if (cur->right) {
// linkto->next = cur->right;
// linkto = cur->right;
// }
// }
// else {
// if (cur->left) {
// linkto = cur->left;
// }
// if (cur->right) {
// if (cur->left) linkto->next = cur->right;
// linkto = cur->right;
// }
// }
}
start = start->left ? start->left : start->right;
//start先更新为下一层的第一个节点(因为原先start就是该层第一个存在子节点的结点,因此其最左子节点就是该层的第一个结点,若存在左子则更新为左子,若不存在左子则一定存在右子,更新为右子)
}
return root;
}