剑指offer 二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:迭代版本:
核心思想是中序遍历,头结点需要单独设置flag变量进行初始化。
if(!s.empty()){ if(flag == 1){ head = s.top(); cur = s.top(); s.pop(); cur -> left = pre; pre -> right = cur; pre = pre -> right; flag = 0; } else{ cur = s.top(); s.pop(); cur -> left = pre; pre -> right = cur; pre = pre -> right; } cur = cur -> right; }
开始写成这样导致错误:数组越界/堆栈溢出。
根本原因在于pre开始初始化为nullptr,不能直接使用pre -> right = cur;这样就是对空指针进行操作。
所以需要改成pre = cur,因为接下来cur会等于栈的下一个元素,pre就在cur的前面了,
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { public: TreeNode* Convert(TreeNode* pRootOfTree){ TreeNode* head = pRootOfTree; TreeNode* pre = nullptr; TreeNode* cur = pRootOfTree; stack<TreeNode*> s; int flag = 1; while(cur != nullptr || !s.empty()){ while(cur != nullptr){ s.push(cur); cur = cur -> left; } if(!s.empty()){ if(flag == 1){ head = s.top(); cur = s.top(); s.pop(); pre = cur; flag = 0; } else{ cur = s.top(); s.pop(); cur -> left = pre; pre -> right = cur; pre = pre -> right; } cur = cur -> right; } } return head; } };
思路2:递归版本实现。
递归的将左子树实现双链表,然后将left链表链接到root上,然后递归的实现右子树,将root链接到右子树上。
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/ class Solution { public: TreeNode* helper(TreeNode* root){ if(root == nullptr){ return nullptr; } TreeNode* leftNode = helper(root -> left);//返回头结点 TreeNode* leftHead = leftNode; while(leftNode != nullptr && leftNode -> right != nullptr){ leftNode = leftNode -> right; } if(leftNode != nullptr){ leftNode -> right = root; root -> left = leftNode; } TreeNode* rightNode = helper(root -> right); if(rightNode != nullptr){ root -> right = rightNode; rightNode -> left = root; } return leftHead != nullptr ? leftHead : root; } TreeNode* Convert(TreeNode* pRootOfTree){ if(pRootOfTree == nullptr){ return nullptr; } return helper(pRootOfTree); } };