将搜索二叉树转换成双向链表

将搜索二叉树转换成双向链表

题目

给定一棵二叉查找树,将它转换成一个有序的双向链表

实现二叉查找树

import random
import operator


class BSTNode():
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None


class BST():
    def __init__(self):
        self.root = None


    def insert(self, node):
        y = None
        x = self.root
        while x:
            y = x
            if node.key < x.key:
                x = x.left
            else:
                x = x.right

        if not y:
            self.root = node
        elif node.key < y.key:
            y.left = node
        else:
            y.right = node


    def search(self, key):
        p = self.root
        while p:
            if p.key == key:
                return p
            elif key < p.key:
                p = p.left
            else:
                p = p.right

        return None


    def traversal(self):
        def traversal_rec(node):
            if not node:
                return

            traversal_rec(node.left)
            l.append(node.key)
            traversal_rec(node.right)

        l = []
        traversal_rec(self.root)
        return l


def make_bst(datas):
    bst = BST()
    for d in datas:
        if bst.search(d) == None:
            node = BSTNode(d)
            bst.insert(node)

    return bst


思路1:使用队列

def convert_bst_to_dlinklist1(bst):
    def inorder(node):
        if not node:
            return

        inorder(node.left)
        q.append(node)
        inorder(node.right)


    if not bst.root:
        return None

    q = []
    inorder(bst.root)

    head = q.pop(0)
    head.left = None

    pre = head
    cur = None
    while q:
        cur = q.pop(0)
        pre.right = cur
        cur.left = pre
        pre = cur

    pre.right = None
    return head

思路2:递归中序遍历

def convert_bst_to_dlinklist2(bst):
    def inorder(node):
        if not node:
            return

        inorder(node.left)
        node.left = d['pre']
        if not d['head']:
            d['head'] = node
        else:
            d['pre'].right = node
        d['pre'] = node
        inorder(node.right)


    d = {'head': None, 'pre': None}
    inorder(bst.root)

    return d['head']

思路3:分治

思路就是左孩子生成一个循环双链表,右孩子生成一个循环双链表,再拼接成一个。
先生成一个循环的双链表可以方便找到链表尾,方便拼接,最后再转换成非循环链表。

def convert_bst_to_dlinklist3(bst):
    def connect(node1, node2):
        if not node1:
            return node2
        if not node2:
            return node1

        tail1, tail2 = node1.left, node2.left
        tail1.right = node2
        node2.left = tail1
        tail2.right = node1
        node1.left = tail2

        return node1


    def convert(node):
        if not node:
            return None

        head_left = convert(node.left)
        head_right = convert(node.right)
        node.left = node
        node.right = node

        return connect(connect(head_left, node), head_right)


    if not bst.root:
        return None

    head = convert(bst.root)
    head.left.right = None
    head.left = None
    return head

测试

def test_bst(count, maxval):
    datas = []
    for _ in range(count):
        d = random.randint(0, maxval)
        datas.append(d)

    bst = make_bst(datas)
    l = bst.traversal()

    datas = sorted(list(set(datas)))
    if not operator.eq(datas, l):
        raise Exception('Error BST')


def dump_dlinklist(head):
    l = []
    p = head
    while p:
        l.append(p.key)
        p = p.right
    
    return l


def dump_dlinklist_reverse(head):
    l = []
    if not head:
        return l

    p = head
    while p.right:
        p = p.right

    while p:
        l.append(p.key)
        p = p.left
    
    return l


def test_convert1(count, maxval):
    datas = []
    for _ in range(count):
        d = random.randint(0, maxval)
        datas.append(d)

    bst = make_bst(datas)
    l = bst.traversal()

    head = convert_bst_to_dlinklist1(bst)
    l1 = dump_dlinklist(head)
    l2 = dump_dlinklist_reverse(head)

    if not operator.eq(l1, l):
        raise Exception('Error convert1')

    l2.reverse()
    if not operator.eq(l1, l2):
        raise Exception('Error convert1')


def test_convert2(count, maxval):
    datas = []
    for _ in range(count):
        d = random.randint(0, maxval)
        datas.append(d)

    bst = make_bst(datas)
    l = bst.traversal()

    head = convert_bst_to_dlinklist2(bst)
    l1 = dump_dlinklist(head)
    l2 = dump_dlinklist_reverse(head)

    if not operator.eq(l1, l):
        raise Exception('Error convert2')

    l2.reverse()
    if not operator.eq(l1, l2):
        raise Exception('Error convert2')


def test_convert3(count, maxval):
    datas = []
    for _ in range(count):
        d = random.randint(0, maxval)
        datas.append(d)

    bst = make_bst(datas)
    l = bst.traversal()

    head = convert_bst_to_dlinklist3(bst)
    l1 = dump_dlinklist(head)
    l2 = dump_dlinklist_reverse(head)

    if not operator.eq(l1, l):
        raise Exception('Error convert2')

    l2.reverse()
    if not operator.eq(l1, l2):
        raise Exception('Error convert2')


if __name__ == '__main__':
    test_bst(0, 1)
    test_bst(1, 1)
    test_bst(10, 10)
    test_bst(100, 100)
    test_bst(1000, 1000)
    test_bst(10000, 10000)

    test_convert1(0, 1)
    test_convert1(1, 1)
    test_convert1(10, 10)
    test_convert1(100, 100)
    test_convert1(1000, 1000)
    test_convert1(10000, 10000)

    test_convert2(0, 1)
    test_convert2(1, 1)
    test_convert2(10, 10)
    test_convert2(100, 100)
    test_convert2(1000, 1000)
    test_convert2(10000, 10000)

    test_convert3(0, 1)
    test_convert3(1, 1)
    test_convert3(10, 10)
    test_convert3(100, 100)
    test_convert3(1000, 1000)
    test_convert3(10000, 10000)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值