36-Leetcode 二叉搜索树与双向链表




题目
二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的 循环双向链表。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
要求不能创建任何新的节点,只能调整树中节点指针的指向。

下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
在这里插入图片描述在这里插入图片描述



思路

我们知道二叉搜索树的特点就是,孩子节点的值 < 根节点的值 < 右孩子节点的值
所以按照 左根右 的顺序进行遍历,即可实现从小到大的顺序。即树的中序遍历。




法一:递归

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <stack>


using namespace std;


struct TreeNode
{
    int data;
    TreeNode * left;
    TreeNode * right;
    TreeNode(int value)
    {
        data = value;
        left = NULL;
        right = NULL;
    }
};


// 借助栈 可以直接在中序遍历的基础上,修改 left 和 right 指针指向的节点
TreeNode * ConvertTreeToList(TreeNode * root)
{
    if(root == NULL)
    {
        return NULL;
    }

    stack<TreeNode *> s;
    s.push(root);
    while(root->left)
    {
        s.push(root->left);
        root = root->left;
    }
    
    TreeNode * result = new TreeNode(0);        // 头结点,不存储数据
    TreeNode * temp = result;
    while (!s.empty())
    {
        TreeNode * cur = s.top();               // 当前栈顶元素
        TreeNode * curRight = cur->right;       // 栈顶元素的右孩子节点

        temp->right = cur;
        cur->left = temp;
        cur->right = NULL;
        temp = temp->right;
        
        cout << temp->data << endl;

        s.pop();
        if(curRight != NULL)
        {
            s.push(curRight);
            
            while (curRight->left)
            {
                s.push(curRight->left);
                curRight = curRight->left;
            }
        }
    }
    result->left = temp;
    temp->right = result->right;
    
    return result;
}

int main()
{
    TreeNode root(4);

    TreeNode node1(2);
    TreeNode node2(5);

    TreeNode node3(1);
    TreeNode node4(3);

    root.left = &node1;
    root.right = &node2;

    node1.left = &node3;
    node1.right = &node4;


  	TreeNode * result = ConvertTreeToList(&root);
    for(int i = 0; i < 5 && result != NULL; i++)
    {
        cout << result->data << " ";
        result = result->right;
    }
    cout << endl;

    return 0;
}



法二:借助栈

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <stack>


using namespace std;


struct TreeNode
{
    int data;
    TreeNode * left;
    TreeNode * right;
    TreeNode(int value)
    {
        data = value;
        left = NULL;
        right = NULL;
    }
};


// 递归版本中序遍历
TreeNode * pre = NULL;
TreeNode * head = NULL;
void DFS(TreeNode * node)
{
    if(node == NULL)
    {
        return;
    }

    // 左
    DFS(node->left);

    // 根--node
    if(pre != NULL)
    {
        pre->right = node;
    }
    else
    {
        head = node;
    }
    node->left = pre;
    pre = node;

    // 右
    DFS(node->right);
}
TreeNode * DFSConvertTreeToList(TreeNode * root)
{
    if(root == NULL)
    {
        return NULL;
    }
    
    // 开始中序递归遍历
    DFS(root);

    head->left = pre;
    pre->right = head;

    return head;
}


int main()
{
    TreeNode root(4);

    TreeNode node1(2);
    TreeNode node2(5);

    TreeNode node3(1);
    TreeNode node4(3);

    root.left = &node1;
    root.right = &node2;

    node1.left = &node3;
    node1.right = &node4;

    TreeNode *result = DFSConvertTreeToList(&root);
    for(int i = 0; i < 5 && result != NULL; i++)
    {
        cout << result->data << " ";
        result = result->right;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值