二叉搜索树与双向链表——27

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

如上所示的二叉搜索树,转换成排序的双向链表就是5-><-6-><-7-><-8-><-9-><-10-><-11。

因为要求转换成双向链表,而恰好二叉树的每个结点都有两个指针,因此可以直接调整指针的指向;对于搜索二叉树,每个结点的左子树的值都比根结点的值要小,而每个右子树的值都比当前结点的值要大,而要求转换成排序的双向链表,因此,对于每个结点的访问顺序应当是先左再中后右,也就是用中序遍历的思路,这样才能保证是有序的;

对于指针的指向,可以将每个结点指向左结点的指针看做双向链表中指向前一个结点的prev指针,而每个结点指向右结点的指针看做双向链表中指向下一个结点的next指针;因此,对于搜索二叉树的最左结点,其实也就是树中的最小值,也就是双向链表的头结点,而树的最右结点就是链表的尾结点也就是最大值;

观察可发现,对于根结点来说,其prev应该指向的是左子树的最右结点,而next应该指向的是右子树的最左结点,因此对于整棵树来说,可以划分成左右子树来进行递归;

程序设计如下:

#include <iostream>
#include <assert.h>
using namespace std;

struct BinaryTreeNode//二叉树结点结构体
{
    int _val;
    BinaryTreeNode *_Lnode;
    BinaryTreeNode *_Rnode;

    BinaryTreeNode(int val)//构造函数
        :_val(val)
         ,_Lnode(NULL)
         ,_Rnode(NULL)
    {}  
};

//创建二叉搜索树,这里简便直接使用前序遍历的方式结构造出了二叉搜索树
BinaryTreeNode* _Create(const int *arr, size_t& index, size_t size)
{
    if((index < size) && (arr[index] != ‘#‘))
    {   
        BinaryTreeNode* root = new BinaryTreeNode(arr[index]);
        root->_Lnode = _Create(arr, ++index, size);
        root->_Rnode = _Create(arr, ++index, size);
        return root;
    }   
    else
        return NULL;
}

BinaryTreeNode* CreateBinaryTree(const int *arr, size_t size)
{
    assert(arr && size);

    size_t index = 0;
    return _Create(arr, index, size);
}

//销毁转变之后的双向链表
void DestoryBinaryTree(BinaryTreeNode* ListNode)
{
    BinaryTreeNode* tmp = ListNode;
    while(ListNode != NULL)
    {
        tmp = ListNode;
        ListNode = ListNode->_Lnode;
        delete tmp;
    }
}

//前序遍历检验二叉树
void PrevOrder(BinaryTreeNode *root)
{
    if(root != NULL)
    {
        cout<<root->_val<<" ";
        PrevOrder(root->_Lnode);
        PrevOrder(root->_Rnode);
    }
}

//二叉搜索树转换为双向链表
void BSTToList(BinaryTreeNode* root, BinaryTreeNode** lastnode)
{
    if(root != NULL)
    {
        BSTToList(root->_Lnode, lastnode);
        root->_Lnode = *lastnode;//如果左结点为空,则当前结点的前指针指向当前链表的最后一个结点

        if(*lastnode != NULL)
            (*lastnode)->_Rnode = root;//将当前链表的最后一个结点的next指针设置为当前结点

        *lastnode = root;//将链表的最后一个结点更新为当前结点
        BSTToList(root->_Rnode, lastnode);//继续遍历右子树直至为空
    }
}

void PrintList(BinaryTreeNode* ListNode)
{
    assert(ListNode);

    BinaryTreeNode* tmp = ListNode;
    cout<<"ListHead:"<<tmp->_val<<endl;
    cout<<"正向打印链表:";
    while(tmp->_Rnode != NULL)//每个结点的右指针指向下一个结点
    {
        cout<<tmp->_val<<"->";
        tmp = tmp->_Rnode;
    }
    cout<<tmp->_val<<"->NULL"<<endl;

    cout<<"ListTail:"<<tmp->_val<<endl;
    cout<<"逆向打印链表:";
    while(tmp->_Lnode != NULL)//每个结点的左指针指向前一个结点
    {
        cout<<tmp->_val<<"->";
        tmp = tmp->_Lnode;
    }
    cout<<tmp->_val<<"->NULL"<<endl;
}

int main()
{
    int arr[] = {8,6,5,‘#‘,‘#‘,7,‘#‘,‘#‘,10,9,‘#‘,‘#‘,11,‘#‘,‘#‘};

    BinaryTreeNode* root = CreateBinaryTree(arr, sizeof(arr)/sizeof(arr[0]));
    cout<<"PrevOrder: ";
    PrevOrder(root);
    cout<<endl;

    BinaryTreeNode* lastnode = NULL;
    BSTToList(root, &lastnode);

    BinaryTreeNode* ListNode = root;
    while(ListNode->_Lnode != NULL)//获取链表的头结点
        ListNode = ListNode->_Lnode;

    PrintList(ListNode);

    DestoryBinaryTree(ListNode);
    return 0;
}

运行程序:

《完》

时间: 2024-11-04 21:44:37

二叉搜索树与双向链表——27的相关文章

剑指offer (27) 二叉搜索树和双向链表

题目:输入一棵BST,将该BST转换成一个排序的双向链表 要求不能创建新的结点,只能调整树中结点指针的指向 在BST中,左子节点的值 小于父节点的之, 父节点的值小于 右子节点的值 因此我们在转换成有序的双向链表时,原先指向左子节点的指针调整为链表中指向前一个结点的指针 原先指向右子节点的指针调整为链表中指向后一个结点的指针 很自然的想到对BST进行中序遍历 当我们遍历转换到根节点(值为10的结点)时,它的左子树已经转换成 一个排序的链表了,并且处在链表中的最后一个结点是当前值最大的结点 我们把

剑指offer之【二叉搜索树与双向链表】

题目: 二叉搜索树与双向链表 链接: https://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5?tpId=13&tqId=11179&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指

数据结构-二叉搜索树与双向链表

题目:输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向. 分析:首先不能创建新的结构,只能在树的前提下进行改变指针的指向.又由于是二叉搜索树,可以通过画图分析可知,二叉搜索树的左子树小于根节点小于右子树,可以发现是个递归过程也是一个中序遍历.所以只需要在中序那块进行指针调整. /* 剑指offer面试题27 */ #include <iostream> using namespace std; struct BinaryTree{

【剑指offer】二叉搜索树转双向链表,C++实现

原创博文,转载请注明出处! # 题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向.要求不能创建任何新的节点,只能调整树中节点指针的指向. 二叉树节点的定义 1 /* 2 struct TreeNode { 3 int val; 4 struct TreeNode *left; 5 struct TreeNode *right; 6 TreeNode(int x) : 7 val(x), left(NULL), right(NU

二叉搜索树与双向链表的转换

题目:输入一棵二叉搜索树(记住是搜索树),将该二叉搜索树转换为一个排序的双向链表.要求:不能创建任何新的结点,只能调整树中结点指针的指向. 分析:如下图 因为是二叉搜索树.所以树的排列是规则的.通过中序遍历正好遍历的是由小到大的序列. 要求说明是只能改变树结点指针的指向,不能增加新的空间和结点.所以在中序遍历的时候,主要是遍历到结点后就去改变指针指向. 为了简单,采用递归进行遍历. 树的结构 struct BinaryTreeNode{ int m_data; BinaryTreeNode* m

编程算法 - 二叉搜索树 与 双向链表 代码(C++)

二叉搜索树 与 双向链表 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目:输入一颗二叉搜索树, 将该二叉搜索树转换成一个排序的双向链表. 要求不能创建不论什么新的结点, 仅仅能调整数中结点的指针的指向. 方法: 使用中序遍历每个结点, 并进行连接, 即左子树指前, 右子树指后, 并保存前一个节点. 本程序包括算法原理, 測试程序, 及 输出. /* * main.cpp * * Created on: 2014.6.12 * Author

剑指OFFER之二叉搜索树与双向链表(九度OJ1503)

题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 输入: 输入可能包含多个测试样例.对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数.接下来的n行,每行为一个二叉搜索树的先序遍历序列,其中左右子树若为空则用0代替. 输出: 对应每个测试案例,输出将二叉搜索树转换成排序的双向链表后,从链表头至链表尾的遍历结果. 样例输入: 1 2 1 0 0 3 0 0 样例输出: 1 2 3 解题思路

二叉搜索树与双向链表-剑指Offer

二叉搜索树与双向链表 题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路 按中序遍历二叉搜索树可从小到大遍历元素 边遍历元素边创建双向链表 最后得到的双向链表的指针指向最后一个节点,所以需要再往回遍历一遍让指针指到头结点 代码 /** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public Tre

24.二叉搜索树与双向链表

二叉搜索树与双向链表 参与人数:2316时间限制:1秒空间限制:32768K 算法知识视频讲解 题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. // 25.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(i