二叉查找树转变为有序双向链表

avatar 2021年6月25日18:13:33 评论 663 次浏览

题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

比如将二元查找树
10
/    \
6       14
/  \     /  \
4     8  12   16
转换成双向链表

4=6=8=10=12=14=16。

一道微软的面试题。

二叉查找树的每个节点都有两个指针,双向链表的节点也是两个指针,不创建新节点只调整指针是可以完成转变的。

对于二叉查找树的每个节点Node,它的左子树中所有的关键字都小于Node的关键字,而右子树中的所有关键字都大于Node的关键字。

采用递归的思维可以很方便的完成转变,将节点的左右子树分别转变成有序链表,然后将节点的指针分别指向这两个链表。

import random
class Node(object):
    def __init__(self,key):
        self.key=key
        self.left=None
        self.right=None
class BSTree(object):
    def __init__(self):
        self.root=None
    def put(self,key):
        if not self.root:
            self.root=Node(key)
        else:
            self.root=self._put(self.root,key)
    def _put(self,node,key):
        if node is None:
            node=Node(key)
        elif key<node.key:
            node.left=self._put(node.left,key)
        elif key>node.key:
            node.right=self._put(node.right,key)
        return node 
    def convert(self):
        if self.root:
            return self._convert(self.root)
    def _convert(self,node,asright=True):
        if not node:
            return None
        else:
            left=self._convert(node.left,False)
            if left:
                left.right=node
                node.left=left
            right=self._convert(node.right)
            if right:
                right.left=node
                node.right=right
            cur=node
            if asright:
                while cur.left:
                    cur=cur.left
            if not asright:
                while cur.right:
                    cur=cur.right
            return cur
                 
             
if __name__=='__main__':
    t=BSTree()  
    for i in range(10):
        t.put(random.randint(0,100))   
    cur=t.convert()
    if cur:
        print cur.key
        while cur.right:
            cur=cur.right
            print cur.key
        while cur.left:
            cur=cur.left
            print cur.key

另一种思路是采用中序遍历的方法。二叉查找树中序遍历的话就是从小到大排列。将遍历过的节点转为有序链表,然后将下一个要遍历的节点加到链表结尾。

import random
class Node(object):
    def __init__(self,key):
        self.key=key
        self.left=None
        self.right=None
class Sorted_LinkedList(object):
    def __init__(self):
        self.head=None
    def travel(self):
        node=self.head
        while node:
            print node.key
            node=node.right
class BSTree(object):
    def __init__(self):
        self.root=None
        self.list=Sorted_LinkedList()
        self.curNode=None
    def put(self,key):
        if not self.root:
            self.root=Node(key)
        else:
            self.root=self._put(self.root,key)
    def _put(self,node,key):
        if node is None:
            node=Node(key)
        elif key<node.key:
            node.left=self._put(node.left,key)
        elif key>node.key:
            node.right=self._put(node.right,key)
        return node 
    def convert(self):
        self._travel(self.root)
        return self.list
    def _travel(self,node):
        if node:
             self._travel(node.left)
             if self.curNode:
                 self.curNode.right=node
                 node.left=self.curNode
             else:
                 self.list.head=node
             self.curNode=node
             self._travel(node.right)
                         
if __name__=='__main__':
    t=BSTree()  
    for i in range(100):
        t.put(random.randint(0,100))
    l=t.convert()
    l.travel()
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: