二叉搜索树和双链表转换

本文介绍了如何将二叉搜索树转换为有序的双向链表,分别提供了递归和非递归两种实现方式。递归版通过中序遍历保存节点并构建链表,非递归版则使用栈模拟递归过程。两种方法都需要理解和处理好边界条件,递归转非递归的实现需要深入理解中序遍历。
摘要由CSDN通过智能技术生成

递归版

由于二叉搜索树本身是有序的,利用中序遍历可以从小到大得到树中的元素,因此在中序遍历的递归过程中,每次保存上一次遍历过的节点,同时将其构造为双向链表,注意最后返回的根节点是中间节点,不是头节点。

TreeNode* pre(TreeNode* root)
{
    TreeNode*last;
    if (root != NULL)
    {
        if (root->left != NULL)
        {
            last = pre(root->left);
            while (last->right != NULL) last = last->right;
            last->right = root;
            root->left = last;
        }

        if (root->right != NULL)
        {
            last = pre(root->right);
            while (last->left != NULL) last = last->left;
            last->left = root;
            root->right = last;
        }
    }
    return root;
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
    if (pRootOfTree == NULL) return NULL;
    if (pRootOfTree->left == NULL && pRootOfTree->right == NULL) return pRootOfTree;
    TreeNode* root = NULL;
    root=pre(pRootOfTree);
    return root;
}

非递归版

其实就是在中序遍历的非递归版中,用栈模拟递归,当前栈顶元素与上次弹出的元素构造双向链表,由于中序遍历中上次弹出的元素必定是小于当前栈顶元素的,因此取上次弹出的元素与当前栈顶的元素构造双向链表能得到最终有序的双向链表。
关键在于非递归的中序遍历的构造。

TreeNode* Convert(TreeNode* pRootOfTree)
{
    if (pRootOfTree == NULL) return NULL;
    if (pRootOfTree->left == NULL && pRootOfTree->right == NULL) return pRootOfTree;
    TreeNode* root = pRootOfTree;
    TreeNode* last = NULL;
    stack<TreeNode*> NodeStack;
    bool isfirst = true;
    do
    {
            while (root )                   //这个循环的头很精妙,保证了右节点能够入栈
            {
                NodeStack.push(root);
                if (root->left == NULL && isfirst)
                {
                    last = root;          //主要为了给last赋初值
                    isfirst = false;
                }
                root = root->left;
            }
                root = NodeStack.top();
                NodeStack.pop();
        //      cout << root->val;
                if (root != last)
                {
                    root->left = last;
                    last->right = root;
                    last = root;
                }
            root = root->right;
    } while (!NodeStack.empty()||root!=NULL);
    while (last->left) last = last->left;
    return last;
}

总的来说,不管递归还是非递归,理解上都有一点难度。递归直观但要注意边界条件,递归转非递归的写法需要多多斟酌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值