[LeetCode] Flatten Binary Tree to Linked List 将二叉树展开成链表 C++ 标签: C++算法编程二叉树展开成链表 2017-05-16 22:

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

         1
        / \
       2   5
      / \   \
     3   4   6

 

The flattened tree should look like:

   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

click to show hints.

Hints:

If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order trave

 

这道题要求把二叉树展开成链表,根据展开后形成的链表的顺序分析出是使用先序遍历,那么只要是数的遍历就有递归和非递归的两种方法来求解,这里我们也用两种方法来求解。首先来看递归版本的,思路是先利用DFS的思路找到最左子节点,然后回到其父节点,把其父节点和右子节点断开,将原左子结点连上父节点的右子节点上,然后再把原右子节点连到新右子节点的右子节点上,然后再回到上一父节点做相同操作。代码如下:

 

解法一:

void flatten(TreeNode *root) {
	if (!root) return;
	if (root->left) flatten(root->left);
	if (root->right) flatten(root->right);
	TreeNode *tmp = root->right;
	root->right = root->left;
	root->left = nullptr;
	while (root->right) root = root->right;
	root->right = tmp;
}


 

例如,对于下面的二叉树,上述算法的变换的过程如下:

复制代码
     1
    / \
   2   5
  / \   \
 3   4   6

     1
    / \
   2   5
    \   \
     3   6
      \    
       4

   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6
复制代码

 

下面我们再来看非迭代版本的实现,这个方法是从根节点开始出发,先检测其左子结点是否存在,如存在则将根节点和其右子节点断开,将左子结点及其后面所有结构一起连到原右子节点的位置,把原右子节点连到元左子结点最后面的右子节点之后。代码如下:

 

解法二:

void flatten(TreeNode *root) {
	TreeNode *np1(root), *np2;
	while (np1) {
		if (np1->left) {
			np2 = np1->left;
			while (np2->right) np2 = np2->right;
			np2->right = np1->right;
			np1->right = np1->left;
			np1->left = nullptr;
		}
		np1 = np1->right;
	}
}


 

例如,对于下面的二叉树,上述算法的变换的过程如下:

复制代码
     1
    / \
   2   5
  / \   \
 3   4   6

   1
    \
     2
    / \
   3   4
        \
         5
          \
           6
           
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6
复制代码

 

前序迭代解法如下:

 

解法三:

void flatten(TreeNode *root) {
	if (!root) return;
	stack<TreeNode*> s;
	s.push(root);
	while (!s.empty()) {
		TreeNode *t = s.top(); s.pop();
		if (t->left) {
			TreeNode *r = t->left;
			while (r->right) r = r->right;
			r->right = t->right;
			t->right = t->left;
			t->left = NULL;
		}
		if (t->right) s.push(t->right);
	}
}

 

此题还可以延伸到用中序,后序,层序的遍历顺序来展开原二叉树,分别又有其对应的递归和非递归的方法,有兴趣的童鞋可以自行实现。

解法四(后序版本):

void flatten(TreeNode* root) {
        stack<TreeNode*> qt;
    	TreeNode *np(root), *prep(nullptr);
    	while (!qt.empty() || np) {
    		if (np) {
    			qt.push(np);
    			np = np->right;
    		}
    		else {
    			np = qt.top();
    			if (!np->left || np->left == prep) {
    				np->left = nullptr;
    				np->right = prep;
    				prep = np;
    				np = nullptr;
    				qt.pop();
    			}
    			else np = np->left;
    		}
    	}
    }



posted @ 2017-05-16 22:04  lmjy  阅读(106)  评论(0编辑  收藏  举报