Description
Given a binary sorting tree (BST), the tree is converted into a bidirectional cyclic linked list. See the illustration below to better understand the meaning of the question.
The BST structure is defined as follows:
struct node { int data; struct node* left; struct node* right;};typedef struct node Node;
Figure 1) 1-5 binary search tree (BST)
Figure 2) an ordered cyclic linked list generated by the above BST conversion. The left and right child pointers of the tree are replaced with Pre and next pointers, pointing to the first and last nodes of the linked list respectively.
The analysis shows that the first response of most people is to traverse the binary tree in a forward order and change the Left and Right pointers of the nodes in the tree. Here, we need to consider how to direct the right pointer of the last node to the first node, as shown in. Figure 3) when a two-way cyclic linked list traverses a binary tree in a central order, every time it traverses a node, we can modify the left pointer of the node to indicate the node to be traversed, we will not use the left pointer in subsequent operations. At the same time, we also need to modify the right pointer of the previous traversal node so that the right pointer of the previous traversal node points to the current node. For example, if we traverse to node 2, we modify the left pointer of Node 2 to point to node 1, and at the same time, we need to modify the right pointer of Node 1 to point to node 2.
Note that the previous traversal node is not the parent node of the current node, but the former node smaller than the current node.
It seems that the problem has been solved and it is slow. In fact, we have put down two important steps. 1) We have no head assignment for the opposite node. 2) The right pointer of the last node does not point to the first node.
The solution to solving these two problems is very simple: update each recursive call
The right pointer of the current traversal node points it to the head of the header node., Update simultaneously
The left pointer of the header node head directs it to the current traversal node.. When the recursive call ends, the head and end nodes of the linked list point to the correct position. Do not forget that there is only one node. Its left and right pointers all point to itself. Figure 4) the solution of two-way circular linked list with only one node is very delicate, because the algorithm is an improvement of the Middle-order traversal, so its time complexity is O (n ), N indicates the number of nodes. Of course, we have added an additional value assignment operation in each recursive call compared to the central order traversal.
// This is an improved middle-order traversal // Prev (initialized to null) is used to track the previous traversal node // when recursion ends, head points to the head void treetodoublylist (node * P, node * & Prev, node * & head) {If (! P) return; treetodoublylist (p-> left, Prev, head); // the left of the current node P refers to the previous node Prev p-> left = Prev; If (prev) prev-> right = P; // The right of the previous node points to the current node else head = P; // if no node exists, set head to the current node (the current node is the smallest node ). // After recursion, the left pointer of the head points to the last node, and the right pointer of the last node points to the head node. Note that the right pointer of P is saved, because the pointer will be modified later in the code. Node * Right = p-> right; head-> left = P; P-> right = head; Prev = P; // update the previous node treetodoublylist (right, Prev, head);} // main function, initialize Prev and head to nullnode * treetodoublylist (node * root) {node * Prev = NULL; node * head = NULL; treetodoublylist (root, prev, head); return head ;}
The Recursive Algorithm of code parsing is quite complex, and it is easy to understand it from the perspective of function functions. The treetodoublylist (node * P, node * & Prev, node * & head) function is to convert the tree with P as the root node into an ordered bidirectional cyclic linked list. Before the function is executed, Prev always points to the previous node before traversing to P. After the function is executed, the prev points to P and the head points to the head node of the linked list. The binary tree shown in the preceding figure is used as an example. The treetodoublylist (node * P, node * & Prev, node * & head) process is as follows: the root node is 4 and treetodoublylist (p-> left, after traversing the left subtree, the left subtree forms an ordered two-way circular linked list 1 = 2 = 3, and the prev points to node 3, head points to the head node 1 of the current bidirectional cyclic linked list. Update p-> left = Prev, that is, the left pointer of 4 points to 3, and set Prev-> right = P, that is, the right pointer of 3 points to 4. At the same time, when the left of head node 1 is updated to the right pointer of node 4 and node 4 is updated to 1, the two-way cyclic linked list is changed to 1 = 2 = 3 = 4, and then the right subtree node is recursively traversed, maintain the nature of a bidirectional cyclic linked list.