[数据结构] 二叉树转双向链表


例题描述

将该二叉树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

二叉树结点结构体定义

struct TreeNode {
	struct TreeNode *left;
	struct TreeNode *right;
	int val;
};

解题思路

我们发现二叉树的中序遍历结果与最后转为的双向链表结果一致,遂采用中序遍历。下面需要找到转后的双向链表的首节点,有两种方法:

  1. 开始操作前在函数栈中循环遍历到二叉树的最左节点并记录下来,最后返回这个节点,即转后双向链表的头节点。
  2. 全局维护一个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即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

giturtle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值