例题描述
将该二叉树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
二叉树结点结构体定义
struct TreeNode {
struct TreeNode *left;
struct TreeNode *right;
int val;
};
解题思路
我们发现二叉树的中序遍历结果与最后转为的双向链表结果一致,遂采用中序遍历。下面需要找到转后的双向链表的首节点,有两种方法:
- 开始操作前在函数栈中循环遍历到二叉树的最左节点并记录下来,最后返回这个节点,即转后双向链表的头节点。
- 全局维护一个
head
指针,它的使命是只在一个场景下进行更改:那就是prev
指针为空的时候,此时node
节点必为最左节点,因为prev
还没有被操作过,更改head
指向后不会再发生改变,最终返回这个head
节点即可。
(相比上一种免去了循环遍历查找最左节点的过程,将遍历查找的过程放在了递归中)
代码实现
/* 第一种 */
TreeNode *prev = NULL; // 保证按有序的顺序调用该函数
void NodeToDoublyLink(TreeNode *root) {
root->left = prev; // node->prev = prev;
if (prev != NULL) {
prev->right = root; // prev->next = node;
}
prev = root;
}
void InOrder(TreeNode *root) {
if (root != NULL) {
InOrder(root->left);
NodeToDoublyLink(root); // 根root
InOrder(root->right);
}
}
TreeNode* Convert(TreeNode* pRootOfTree) {
if (!pRootOfTree) return nullptr;
TreeNode *head = pRootOfTree; //双向链表头节点
// 二叉树最左节点即为双向链表头节点
while (head->left) head = head->left;
InOrder(pRootOfTree);
return head;
}
/* 第二种 */
TreeNode *prev = NULL;
TreeNode *head = NULL; // 全局指针
void NodeToDoublyLink(TreeNode *root) {
if (prev == NULL) head = root; // 此时为赋值head的时机,节点为最左节点
root->left = prev;
if (prev != NULL) {
prev->right = root;
}
prev = root;
}
void InOrder(TreeNode *root) {
if (root != NULL) {
InOrder(root->left);
NodeToDoublyLink(root);
InOrder(root->right);
}
}
TreeNode* Convert(TreeNode* pRootOfTree) {
if (!pRootOfTree) return nullptr;
InOrder(pRootOfTree);
return head;
}
代码实现二
Node* Convert(Node* pRoot){
Node* pLastNode = NULL;
ConvertNode(pRoot, pLastNode);
//pLastNode 指向双向链表的尾结点,需要返回的是头结点。
Node* pHead = pLastNode;
while (pHead && pHead->pLeft ){ //从当前位置找到头结点
pHead = pHead->Left;
}
return pHead;
}
void ConvertNode(Node* pNode, Node*& pLastNode){
if (pNode == NULL)
return;
Node* pCur = pNode;
//树的最左节点作为链表的头
if (pCur->Left)
ConvertNode(pCur->Left, pLastNode);
pCur->Left = pLastNode; //前指针
if (pLastNode)
pLastNode->Right = pCur;
pLastNode = pCur; //后指针
if (pCur->Right)
ConvertNode(pCur->Right, pLastNode);
}
如果ConvertNode
函数的第二个参数为二级指针:
则除了将Node*& pLastNode
改为Node** pLastNode
之外,在代码中将所有的pLastNode
改为*pLastNode
即可。