Zig-Zag traversal
#include <bits/stdc++.h> // Includes iostream, queue, vector, etc. for common operations#include "BinaryTree.h" // Assumed to contain Node class and buildTree function definitions
using namespace std; // Uses the standard namespace
// Function to perform Zig-Zag (Spiral) Level Order Traversal// Visits nodes level by level, alternating direction (L->R, R->L, L->R, ...)vector<int> ZigZag(Node* root) { // Base Case: If the tree is empty, return an empty vector. if(root == NULL) { return {}; }
queue<Node*> Q; // Queue for standard BFS traversal vector<int> answer; // Final vector to store the zig-zag traversal result
Q.push(root); // Start by pushing the root node bool L2R = true; // Flag to track direction: true for Left-to-Right, false for Right-to-Left
// Main loop: Continue as long as there are nodes in the queue (levels to process) while(!Q.empty()) { int levelSize = Q.size(); // Get the number of nodes in the current level vector<int> currentLevelNodes(levelSize); // Temporary vector to store nodes of the current level in correct order
// Process all nodes in the current level for(int i = 0; i < levelSize; i++) { Node* frontNode = Q.front(); // Get the node at the front of the queue Q.pop(); // Remove the node from the queue
// Determine the index to place the node's data in the 'currentLevelNodes' vector // If L2R, place normally (0, 1, 2...). If !L2R, place in reverse (size-1, size-2...). int index = L2R ? i : levelSize - i - 1; currentLevelNodes[index] = frontNode->data; // Store data at the calculated index
// Enqueue children for the next level (always Left then Right for standard BFS queue order) if(frontNode->left) { Q.push(frontNode->left); } if(frontNode->right) { Q.push(frontNode->right); } }
// After processing the entire level, toggle the direction for the next level L2R = !L2R;
// Add the nodes from the current level's ordered vector to the final answer vector for(int data : currentLevelNodes) { answer.push_back(data); } }
return answer; // Return the complete zig-zag traversal}
int main() { Node* root = NULL; // Initialize the root of the tree to NULL
// Build the tree using 'buildTree' function (assumed to be in "BinaryTree.h") // It typically takes input in a pre-order fashion. root = buildTree(root);
// Perform Zig-Zag Traversal and get the result vector<int> result = ZigZag(root);
// Print the Zig-Zag Traversal result cout << endl << "Zigzag Traversal : "; for(int data : result) { cout << data << " "; } cout << endl;
return 0; // End of the program}
/*Example INPUTs for buildTree function (for reference):
1. Input: 1 2 3 -1 -1 5 -1 -1 4 -1 6 7 -1 -1 8 -1 -1 Tree Structure: 1 / \ 2 4 / \ / \ 3 5 6 8 / 7 Level 0 (L->R): 1 Level 1 (R->L): 4 2 Level 2 (L->R): 3 5 6 8 Level 3 (R->L): 7 Output: Zigzag Traversal : 1 4 2 3 5 6 8 7
2. Input: 7 9 8 10 -1 -1 9 -1 -1 8 -1 -1 7 6 -1 -1 -1 Tree Structure: 7 / \ 9 7 / \ \ 8 9 6 / / 10 8 Level 0 (L->R): 7 Level 1 (R->L): 7 9 Level 2 (L->R): 8 9 6 Level 3 (R->L): 8 10 Output: Zigzag Traversal : 7 7 9 8 9 6 8 10*/1. Binary Tree Node Structure
- A
Nodein a Binary Tree typically consists of:data: The value stored in the node.left: A pointer to the left child node.right: A pointer to the right child node.
2. Level Order Traversal (BFS) Basics
- Standard Level Order Traversal (Breadth-First Search) visits nodes level by level, always from left to right within each level. It typically uses a queue.
3. Zig-Zag (Spiral) Traversal
- Definition: A variation of level order traversal where nodes are visited level by level, but the direction of traversal alternates for each level:
- Level 1: Left to Right
- Level 2: Right to Left
- Level 3: Left to Right
- And so on…
4. Algorithm: ZigZag(Node* root)
-
Core Idea: Uses a standard BFS (Queue) to process nodes level by level. For each level, it determines the direction (Left-to-Right or Right-to-Left) and stores the nodes in a temporary vector in that specific order before adding them to the final result.
-
Data Structures Used:
queue<Node*> Q: For performing standard Level Order Traversal (BFS). Nodes are enqueued/dequeued in standard left-to-right order.vector<int> result: A temporary vector to store the node data for the current level in the correct zig-zag order.bool L2R: A flag to keep track of the current level’s direction (truefor Left-to-Right,falsefor Right-to-Left).
-
Steps:
- Handle Empty Tree: If
rootisNULL, return an empty vector. - Initialization:
- Push
rootinto the queueQ. - Initialize
L2R = true(start with Left-to-Right for the first level).
- Push
- Main Loop (
while(!Q.empty())): Continues as long as there are nodes to process.- Get Level Size:
int size = Q.size();determines how many nodes are in the current level. - Prepare Current Level Storage:
vector<int> result(size);creates a temporary vector of the correct size for the current level’s nodes. - Process Current Level Nodes: Loop
for(int i=0; i<size; i++):Node* FrontNode = Q.front(); Q.pop();: Dequeue the node.- Determine Placement Index:
- If
L2Ristrue(Left-to-Right):index = i. Nodes are placed directly at their sequential index. - If
L2Risfalse(Right-to-Left):index = size - i - 1. Nodes are placed at the reverse index to achieve right-to-left order.
- If
result[index] = FrontNode->data;: Store the node’s data at the calculated index in theresultvector.- Enqueue Children: If
FrontNode->leftexists, enqueue it. IfFrontNode->rightexists, enqueue it. (Children are always enqueued in standard left-to-right order; the zig-zag effect comes from how they are placed inresult).
- Toggle Direction: After processing all nodes for the current level,
L2R = !L2R;flips the direction for the next level. - Append to Final Answer: Iterate through the
resultvector and add its elements to theanswervector.
- Get Level Size:
- Return: Return the
answervector containing all nodes in zig-zag order.
- Handle Empty Tree: If
5. Complexity Analysis
- Time Complexity:
O(N)- Each node is enqueued and dequeued exactly once. Operations within the loop (dequeuing, placing in
result, enqueuing children) are constant time. The final loop to appendresulttoansweralso processes each node once overall.
- Each node is enqueued and dequeued exactly once. Operations within the loop (dequeuing, placing in
- Space Complexity:
O(W)Q(queue) stores nodes up to the maximum width of the tree (W).result(vector) temporarily stores nodes of the widest level (W).answer(vector) stores allNnodes.- So, the dominant space is
O(N)for theanswervector, andO(W)for auxiliary space. In the worst case (complete binary tree),Wcan beN/2, soO(N).