二元查找树转排序双向链表算法解析

5星 · 超过95%的资源 需积分: 50 51 下载量 195 浏览量 更新于2024-08-02 2 收藏 784KB PDF 举报
“程序员面试精选100题.pdf”是一份针对程序员面试的资料,包含了100个重要的面试问题,其中特别提到了“把二元查找树转变成排序的双向链表”的题目。这个题目要求在不创建新节点的情况下,通过调整二元查找树中的指针,将其转换为一个有序的双向链表。 面试题目的具体内容是:给定一个二元查找树,例如树结构如下: ``` 10 / \ 6 14 / \ / \ 4 8 12 16 ``` 目标是将其转换成如下排序的双向链表: ``` 4 <-> 6 <-> 8 <-> 10 <-> 12 <-> 14 <-> 16 ``` 对于这个问题,有两种常见的递归解决方案: 思路一: 1. 首先,递归处理左子树,将左子树转换成一个排序的左子链表。 2. 然后,递归处理右子树,将其转换成右子链表。 3. 当处理到当前节点时,将左子链表的最后一个节点(最大值)与当前节点连接,再将当前节点与右子链表的第一个节点(最小值)连接。 4. 从根节点开始,逐步调整所有节点的指针,最终完成整个树的转换。 思路二: 1. 使用中序遍历的方法,按顺序访问所有节点。 2. 在访问每个节点时,假设前一个访问的节点已构成链表,然后将当前节点插入到链表的末尾。 3. 遍历完整个树后,所有节点就形成了一个有序的双向链表。 在C++中,二元查找树的节点数据结构可以表示为: ```cpp struct BSTreeNode { int m_nValue; // 节点的值 BSTreeNode* m_pLeft; // 左孩子指针 BSTreeNode* m_pRight; // 右孩子指针 }; ``` 思路一对应的代码可能如下(简化版): ```cpp BSTreeNode* ConvertToDoubleLinkedList(BSTreeNode* pNode, bool asRight) { if (pNode == nullptr) return nullptr; // 递归处理左子树 BSTreeNode* pLeft = ConvertToDoubleLinkedList(pNode->m_pLeft, false); // 递归处理右子树 BSTreeNode* pRight = ConvertToDoubleLinkedList(pNode->m_pRight, true); // 连接左右子树和当前节点 if (pLeft) { pLeft->m_pRight = pNode; pNode->m_pLeft = pLeft; } if (pRight) { pNode->m_pRight = pRight; pRight->m_pLeft = pNode; } // 返回结果,如果是右子树则返回最小节点,否则返回最大节点 return asRight ? pRight : pLeft; } ``` 这段代码展示了如何使用递归将二元查找树转换为双向链表。在实际的面试或编码过程中,还需要考虑边界条件和错误处理,以及对原始数据结构的保护,避免意外修改。