《剑指offer》(面试题27):二叉搜索树与双向链表

27 篇文章 0 订阅
23 篇文章 0 订阅

中序遍历算法的特点是按照从小到大的顺序遍历二叉树的每一个结点。

前言

在计算机领域有一类算法叫分治法,即“分而治之”。采用的就是各个击破的思想,我们把分解后的小问题各个解决,然后把小问题的解决方案结合起来解决大问题。

题目描述

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

解题思路

哇偶,中序遍历啊!中序遍历,递归和循环都可以撒~

二叉搜索树是一种排序的数据结构,每个结点都有两个指向子结点的指针。在双向链表中,每个结点也有两个指针,他们分别指向前一个结点和后一个结点。在二叉搜索树中,左子结点的值总是小于父结点的值,右子结点的值总是大于父结点的值。因此我们在转换成排序双向链表时,原先指向左子结点的指针调整为链表中指向前一结点的指针,原先指向右子结点的指针调整为链表中指向后一个结点指针。

中序遍历在二叉搜索树中的特点是按照从小到大的顺序遍历二叉树的每一个结点。下图中,我们可以把树分成三个部分:值为10的结点、根结点为6的左子树、根结点为14的右子树。根绝排序链表的定义,值为10的结点将和它的左子树的最大一个结点链接起来,同时它还将和右子树最小的结点链接起来。


按照中序遍历的顺序,当我们遍历转换到根结点时,它的左子树已经转换成一个排序的链表了,并且处在链表中最后一个的结点是当前值最大的结点。我们把值为8的结点和根结点链接起来,10就成了最后一个借点,接着我们就去遍历转换右子树,并把根结点和右子树中最小的结点链接起来。

下面个分别用C/C++和Python来实现,其中递归1是书中的解法,递归2是更加容易理解的解法,原理都是一样的,只不过递归1中涉及到指针的指针,容易把自己搞蒙。

Python版代码实现

递归

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Convert(self, pRootOfTree):
        # write code here
        if not pRootOfTree:
            return None
        if not pRootOfTree.left and not pRootOfTree.right:
            return pRootOfTree
        #遍历左子树
        pLeft = self.Convert(pRootOfTree.left)
        pCurrent = pLeft
        #定位至左子树最右的一个结点
        while pCurrent and pCurrent.right:
            pCurrent = pCurrent.right
        #如果左子树不为空,则将当前pRootOfTree加到左子树链表
        if pLeft:
            pCurrent.right = pRootOfTree
            pRootOfTree.left = pCurrent
        #遍历右子树
        pRight = self.Convert(pRootOfTree.right)
        #如果右子树不为空,则将当前pRootOfTree加到右子树链表
        if pRight:
            pRight.left = pRootOfTree
            pRootOfTree.right = pRight

        return pLeft if pLeft else pRootOfTree

循环

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Convert(self, pRootOfTree):
        # write code here
        s = []
        pCurrent = pRootOfTree
        pHeadOfList = None
        pLastNodeInList = None
        while pCurrent or s:
            while pCurrent:
                s.append(pCurrent)
                pCurrent = pCurrent.left
            if s:
                pCurrent = s.pop()
                if pLastNodeInList:
                    pLastNodeInList.right = pCurrent
                    pCurrent.left = pLastNodeInList
                else:
                    pHeadOfList = pCurrent
                pLastNodeInList = pCurrent
                pCurrent = pCurrent.right
        return pHeadOfList



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值