解法一:中序遍历
type Node struct {
Val int
Left *Node
Right *Node
}
// 全局变量:创建前驱节点和头结点的引用
var pre, head *Node
// treeToDoublyList 将二叉搜索树转换为循环双向链表
// 中序遍历完成后,head指向双向链表中的头结点,pre指向尾节点
func treeToDoublyList(root *Node) *Node {
if root == nil {
return nil
}
pre, head = nil, nil // 初始化全局变量
dfs(root) // 中序遍历构建双向链表
// 由于要求是循环链表,需要再修改头尾节点的指针指向
head.Left = pre
pre.Right = head
return head
}
// dfs 递归实现中序遍历
// 中序遍历顺序为:左子树 → 当前节点 → 右子树
func dfs(cur *Node) {
if cur == nil {
return // 越过叶子节点,直接返回
}
dfs(cur.Left) // 递归中序遍历左子树
// -----中序遍历处理逻辑-----
// pre用于记录双向链表中位于cur左侧的节点,即上一次迭代中的cur
if pre == nil {
// 当pre==nil时,说明cur左侧没有节点,即此时cur为双向链表中的头节点
head = cur
} else {
// 反之,pre不为空,cur左侧存在节点,此时需要修改双向链表节点的指向
pre.Right = cur
cur.Left = pre
}
pre = cur // 更新pre为当前节点,用于下一次迭代
dfs(cur.Right) // 递归中序遍历右子树
}