Python程序员面试算法宝典---解题总结: 第三章 二叉树 3.6 如何把二叉树转换为双向链表

# -*- coding: utf-8 -*-

'''
Python程序员面试算法宝典---解题总结: 第三章 二叉树 3.6 如何把二叉树转换为双向链表

题目:
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的节结点,
只能调整结点的指向。例如:
                    4
        2                       6
    1       3               5       7
翻转后变为:
1<-->2<-->3<-->4<-->5<-->6<-->7

分析:
这里的二元查找树的特点就是中序遍历结果是有序的。
如果用中序遍历,确认当前节点和下一个节点,就可以构造这种指向。
树的节点有left和tight,双向链表是prev和next。
一种简单的转换方式就是讲:
left转换为prev
right转换为next。

如果用中序遍历的递归方式,很难确定当前节点和下一个节点。
采用中序遍历的非递归方式有可能完成这个任务。

中序遍历的非递归方式是:
步骤1: 如果当前节点有左孩子,则一直寻找其左孩子,直到节点的左孩子为空,
        那么当前节点即为所求。
步骤2: 遍历的过程中不断在队列中加入遍历的节点,则遍历完当前节点后,此时必定存在该节点的父节点;
       此时遍历其父节点,由于其左孩子已经遍历过,则遍历该父节点的右孩子,以该父节点的右孩子为
        输入节点,重复步骤1

关键:
1 书上解法
设定begin和end指针,
采用中序遍历,
先递归遍历左子树
将当前节点的左指针指向end,
如果end为空,则表示此时是第一个节点,就令begin指针为当前节点;
否则,令end的右指针指向当前节点;
令当前节点为end
最后递归遍历右子树

参考:
Python程序员面试算法宝典
'''

import Queue

class BinaryTreeNode(object):
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right
        self.isVisited = False


def buildBinarySearchTree(data, begin, end):
    if not data:
        return
    if begin > end:
        return
    if begin == end:
        root = BinaryTreeNode(data[begin])
        return root
    length = end - begin + 1
    middle = length / 2 + begin
    root = BinaryTreeNode(data[middle])
    left = buildBinarySearchTree(data, begin, middle - 1)
    right = buildBinarySearchTree(data, middle + 1, end)
    if left:
        root.left = left
    if right:
        root.right = right
    return root


# class MyTree(object):
#     def __init__(self):
#         self.queue = Queue.Queue()
#         self.result = list()
#
#     def inOrder(self, root):
#         if not root:
#             return
#         self.queue.put(root)
#         node = root
#         while not self.queue.empty():
#             # 如果当前节点的左孩子已经遍历过,说明此事应该遍历当前节点本身,并以当前节点的右孩子继续进行遍历
#             if node.left is None or node.left.isVisited:
#                 node.left
#                 node.isVisited = True
#                 if node.right
#                 self.queue.put(node.right)
#             else:
#                 pass
#             # 左子树为空,说明已经找到自己需要的节点
#             if left is None:
#                 left.isVisited = True
#                 self.result.append(left)
#                 # 设置新的节点
#             else:
#                 # 如果左节点不为空,则加入到队列,并继续遍历
#                 self.queue.put(left)
#                 node = left

class MyTree(object):
    def __init__(self):
        self.begin = None
        self.end = None

    def inOrder(self, root):
        if not root:
            return
        self.inOrder(root.left)
        root.left = self.end
        if self.end:
            self.end.right = root
        else:
            self.begin = root
        self.end = root
        self.inOrder(root.right)


def process():
    data = list(range(1, 8))
    root = buildBinarySearchTree(data, 0, len(data) - 1)
    a = 1
    tree = MyTree()
    tree.inOrder(root)
    node = tree.begin
    result = ""
    while node:
        if result:
            result += "->" + str(node.data)
        else:
            result = str(node.data)
        node = node.right
    print result
    node = tree.end
    result = ""
    while node:
        if result:
            result += "->" + str(node.data)
        else:
            result = str(node.data)
        node = node.left
    print result


if __name__ == "__main__":
    process()

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/91489248