To create a doubly linked list from a binary tree, we can use a modified depth-first search (DFS) algorithm to traverse the binary tree and create a doubly linked list.
Here are the steps to create a doubly linked list from a binary tree:
- Create a new doubly linked list with a head and a tail pointer, both initialized to null.
- Traverse the binary tree in-order using DFS. When visiting a node, do the following:
- Create a new node for the doubly linked list.
- Set the value of the new node to the value of the current node in the binary tree.
- Add the new node to the end of the doubly linked list using the tail pointer.
- Set the previous pointer of the new node to the current tail pointer.
- Set the next pointer of the current tail pointer to the new node.
- Update the tail pointer to point to the new node.
- Once the binary tree has been fully traversed, return the head pointer of the doubly linked list.
1
/ \
2 3
/ \ \
4 5 6
Traversing the binary tree in-order using DFS yields the sequence 4, 2, 5, 1, 3, 6. As we traverse the binary tree, we create new nodes in the doubly linked list and add them to the end of the list. The resulting doubly linked list looks like this:
Null<- | 4 | <=> | 2 | <=> | 5 | <=> | 1 | <=> | 3 | <=> | 6 | -> Null
Here’s an example of a binary tree and the resulting doubly linked list:
class TreeNode(var value: Int, var left: TreeNode? = null, var right: TreeNode? = null)
class DoublyLinkedListNode(var value: Int, var prev: DoublyLinkedListNode? = null, var next: DoublyLinkedListNode? = null)
fun binaryTreeToDoublyLinkedList(root: TreeNode?): DoublyLinkedListNode? {
if (root == null) {
return null
}
var head: DoublyLinkedListNode? = null
var tail: DoublyLinkedListNode? = null
fun dfs(node: TreeNode) {
val listNode = DoublyLinkedListNode(node.value)
if (head == null) {
head = listNode
}
if (tail != null) {
tail!!.next = listNode
listNode.prev = tail
}
tail = listNode
node.left?.let { dfs(it) }
node.right?.let { dfs(it) }
}
dfs(root)
return head
}
fun main() {
// Create a binary tree
val root = TreeNode(1,
TreeNode(2,
TreeNode(4),
TreeNode(5)
),
TreeNode(3,
null,
TreeNode(6)
)
)
// Convert the binary tree to a doubly linked list
val head = binaryTreeToDoublyLinkedList(root)
// Print the resulting doubly linked list
var current: DoublyLinkedListNode? = head
while (current != null) {
print("${current.value} ")
current = current.next
}
println()
}
- The function takes a single argument,
root
, which is aTreeNode
representing the root of the binary tree to be converted to a doubly linked list. - The function begins by checking if the
root
isnull
. If it is, then the function returnsnull
. - If the
root
is notnull
, the function initializes two variables,head
andtail
, tonull
. These variables will be used to build the doubly linked list as we traverse the binary tree. - The function defines a nested function,
dfs
, which performs a depth-first search of the binary tree and creates a newDoublyLinkedListNode
for each node in the tree. The function takes a single argument,node
, which is aTreeNode
representing the current node in the binary tree. - Inside the
dfs
function, a newDoublyLinkedListNode
is created with the same value as the currentTreeNode
. This new node is added to the end of the doubly linked list using thetail
variable. Iftail
is notnull
, thenext
pointer of the current tail is set to the new node, and theprev
pointer of the new node is set to the current tail. Thetail
variable is then updated to point to the new node. - The
dfs
function then recursively calls itself on the left and right children of the current node, if they exist. - After the
dfs
function has finished traversing the binary tree, it returns thehead
variable, which is the head of the resulting doubly linked list. - Finally, in the
main
function, a binary tree is created and passed to thebinaryTreeToDoublyLinkedList
function. The resulting doubly linked list is then printed to the console by iterating over each node in the list and printing its value.
The time complexity of the binaryTreeToDoublyLinkedList
function is O(n), where n is the number of nodes in the binary tree. This is because the function performs a depth-first traversal of the entire tree, visiting each node once.
The space complexity of the function is also O(n), where n is the number of nodes in the binary tree. This is because the function creates a new DoublyLinkedListNode
for each node in the binary tree, and each node has a constant amount of space overhead (i.e., the value of the node and pointers to the previous and next nodes). In the worst case, when the binary tree is a linear chain (i.e., each node has only one child), the doubly linked list will also be a linear chain with n nodes, so the space complexity is O(n).