[程序员面试题精选100题]1.把二叉查找树转变成排序的双向链表

简介:

【题目】

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

比如将二叉查找树
                                            10
                                          /    \
                                        6       14
                                      /  \     /  \
                                         4     8  12    16
转换成双向链表4=6=8=10=12=14=16


参考:程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表

【思路】

本题是微软的面试题。很多与树相关的题目都是用递归的思路来解决,本题也不例外。

我们可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,

我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。

【代码】

/*********************************
*   日期:2013-12-17
*   作者:SJF0115
*   题目: 把二元查找树转变成排序的双向链表
*   来源:微软
*   分类:经典面试题
**********************************/
#include <iostream>
using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x):val(x),left(NULL),right(NULL){}
};
//中序遍历过程中改变
// 转换后pre指向双向链表的最后一个节点
// root成为中间节点
void ConvertDoubleList(TreeNode* root, TreeNode*& pre) {
    if(root == NULL){
        return;
    }
    // 当前节点
    TreeNode* cur = root;
    // 左子节点
    if(cur->left){
        ConvertDoubleList(cur->left,pre);
    }
    // 中间节点 改成双向链表
    cur->left = pre;
    if(pre != NULL){
        pre->right = cur;
    }//if
    // 前一节点
    pre = cur;
    // 右子节点
    if(cur->right){
        ConvertDoubleList(cur->right,pre);
    }//if
}
// 二叉查找树插入
void TreeInsert(TreeNode*& root,int val){
    // 创建新节点
    TreeNode* node = new TreeNode(val);
    if(root == NULL){
        root = node;
    }
    else{
        TreeNode *pre = NULL;
        TreeNode *cur = root;
        // 寻找插入位置
        while(cur){
            // 父节点
            pre = cur;
            // 沿左子树方向下降
            if(val < cur->val){
                cur = cur->left;
            }
            // 沿右子树方向下降
            else{
                cur = cur->right;
            }
        }//while
        // 插入左子结点处
        if(val < pre->val){
            pre->left = node;
        }
        // 插入右子结点处
        else{
            pre->right = node;
        }//if
    }//if
}

// 中序遍历
void InOrder(TreeNode* root){
    if(root == NULL){
        return;
    }
    if(root->left){
        InOrder(root->left);
    }
    cout<<root->val<<endl;
    if(root->right){
        InOrder(root->right);
    }
}
//输出双向链表
void PrintDoubleList(TreeNode *head){
    TreeNode *cur = head;
    if(cur == NULL){
        return;
    }
    // 反向遍历
    while(cur->left){
        cout<<cur->val<<"->";
        cur = cur->left;
    }
    cout<<cur->val<<"->NULL"<<endl;
    // 正向遍历
    while(cur){
        cout<<cur->val<<"->";
        cur = cur->right;
    }
    cout<<"NULL"<<endl;
}

int main(){
    int array[] = {10,6,14,4,8,12,16};
    // 创建二叉查找树
    TreeNode *root = NULL;
    for(int i = 0;i < 7;i++){
        TreeInsert(root,array[i]);
    }
    // 中序遍历
    // InOrder(root);
    // 二叉查找树转换为双向链表
    TreeNode *pre = NULL;
    ConvertDoubleList(root,pre);
    // 打印双向链表
    PrintDoubleList(pre);
    return 0;
}







目录
相关文章
|
机器学习/深度学习 算法
24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交
1. **两两交换链表中的节点**:通过引入虚拟头结点,使所有节点都能采用统一的交换逻辑,避免对头结点单独处理。 2. **删除链表的倒数第N个节点**:利用双指针技巧,让快慢指针保持N个节点的距离,当快指针到达末尾时,慢指针正好指向待删除节点的前一个节点。 3. **链表相交**:先计算两链表长度并调整起点,确保从相同距离末尾的位置开始遍历,从而高效找到相交节点或确定无交点。 以上方法均在时间复杂度和空间复杂度上进行了优化,适合用于理解和掌握链表的基本操作及常见算法设计思路。
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
算法 程序员 Go
PHP 程序员学会了 Go 语言就能唬住面试官吗?
【9月更文挑战第8天】学会Go语言可提升PHP程序员的面试印象,但不足以 solely “唬住” 面试官。学习新语言能展现学习能力、拓宽技术视野,并增加就业机会。然而,实际项目经验、深入理解语言特性和综合能力更为关键。全面展示这些方面才能真正提升面试成功率。
253 10
|
JavaScript 前端开发 小程序
CoderGuide 程序员前后端面试题库,打造全网最高质量题库
CoderGuide涵盖范围包括且不限于:前端面试题(Vue,React,JS,HTTP,HTML,CSS面试题等),后端面试题(Java,Python,Golang,PHP,Linux,Mysql面试题等),以及算法面试题,大厂面试题,高频面试题,校招面试题等,你想要的,这里都有!
437 2
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
250 0
|
存储 算法 安全
HashMap常见面试题(超全面):实现原理、扩容机制、链表何时升级为红黑树、死循环
HashMap常见面试题:红黑树、散列表,HashMap实现原理、扩容机制,HashMap的jd1.7与jdk1.8有什么区别,寻址算法、链表何时升级为红黑树、死循环
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
245 0
|
存储 算法 Python
【面试题】合井K个升序链表
【面试题】合井K个升序链表
159 0
|
存储 Java
【Java集合类面试十】、HashMap中的循环链表是如何产生的?
在多线程环境下,HashMap在扩容时如果发生条件竞争,元素的插入顺序可能形成循环链表,导致死循环。
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
335 0