Vertical Order traversal
#include <bits/stdc++.h> // Includes common standard libraries (iostream, queue, vector, map, utility for pair)#include "BinaryTree.h" // Assumed to contain Node class and buildTree function definitions
using namespace std; // Uses the standard namespace
// Function to perform Vertical Order Traversal of a Binary Tree// Nodes are printed column by column, from top to bottom within each column.vector<int> VerticalOrder(Node* root) { // Base Case: If the tree is empty, return an empty vector. if(root == NULL) { return {}; }
vector<int> answer; // Final vector to store the vertical order traversal result
// map<Horizontal_Distance, map<Level, vector<Node_Data>>> // NodeMap stores nodes grouped by HD, then by Level, then collects data. // std::map automatically keeps keys (HDs and Levels) sorted. map<int, map<int, vector<int>>> NodeMap;
// Queue for BFS traversal: stores {Node*, {Horizontal_Distance, Level}} queue<pair<Node*, pair<int, int>>> Q;
// Start BFS: push root with HD=0 and Level=0 Q.push(make_pair(root, make_pair(0,0)));
// Perform BFS traversal while(!Q.empty()) { // Get the front element from the queue pair<Node*, pair<int, int>> temp = Q.front(); Q.pop(); // Remove it from the queue
// Extract node, horizontal distance (HD), and level Node* FrontNode = temp.first; int HorizDist = temp.second.first; int Lvl = temp.second.second;
// Store the node's data in the NodeMap based on its HD and Level NodeMap[HorizDist][Lvl].push_back(FrontNode->data);
// Enqueue left child if it exists: HD decreases by 1, Level increases by 1 if(FrontNode->left) { Q.push(make_pair(FrontNode->left, make_pair(HorizDist-1, Lvl+1))); }
// Enqueue right child if it exists: HD increases by 1, Level increases by 1 if(FrontNode->right) { Q.push(make_pair(FrontNode->right, make_pair(HorizDist+1, Lvl+1))); } }
// After BFS, NodeMap contains all nodes sorted by HD, then by Level. // Now, iterate through the map to populate the final answer vector. for(auto const& hd_entry : NodeMap) { // Iterate through each Horizontal Distance // hd_entry.first is the HD, hd_entry.second is the inner map<Level, vector<int>> for(auto const& level_entry : hd_entry.second) { // Iterate through each Level within this HD // level_entry.first is the Level, level_entry.second is the vector<int> of node data for(int node_data : level_entry.second) { // Iterate through node data at this HD and Level answer.push_back(node_data); // Add to final answer } } }
return answer; // Return the complete vertical order 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 Vertical Order Traversal and get the result vector<int> result = VerticalOrder(root);
// Print the Vertical Order Traversal result cout << endl << "Vertical Order 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 6 -1 -1 8 -1 -1 4 -1 7 -1 9 10 -1 -1 11 -1 -1 (Assuming this input generates the tree as discussed in previous responses, e.g., the complex one) Tree Structure example: 1 (0,0) / \ 2(-1,1) 4(1,1) / \ \ 3(-2,2) 5(0,2) 7(2,2) / \ \ 6(-1,3) 8(1,3) 9(3,3) / 10(2,4) / 11(1,5)
HD: -2 -> 3 HD: -1 -> 2, 6 HD: 0 -> 1, 5 HD: 1 -> 4, 8, 11 HD: 2 -> 7, 10 HD: 3 -> 9
Output: Vertical Order Traversal : 3 2 6 1 5 4 8 11 7 10 9 (The exact order might slightly vary based on how nodes on same HD & Level are added, but map handles levels. The crucial bit is that nodes with same HD and same LEVEL are added to the vector in order of their BFS discovery)
2. Input: 1 2 4 -1 -1 5 -1 -1 3 6 -1 8 -1 -1 7 -1 9 -1 -1 Tree Structure: 1 (0,0) / \ 2(-1,1) 3(1,1) / \ / \ 4(-2,2) 5(0,2) 6(0,2) 7(2,2) / \ / \ 8(-1,3) 9(1,3)
HD: -2 -> 4 HD: -1 -> 2, 8 HD: 0 -> 1, 5, 6 HD: 1 -> 3, 9 HD: 2 -> 7
Output: Vertical Order Traversal : 4 2 8 1 5 6 3 9 7 (Here, for HD=0 and Level=2, 5 comes before 6 as it's processed first in BFS).*/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. Vertical Order Traversal Definition
- Definition: Nodes are traversed and collected column by column based on their horizontal distance from the root.
- All nodes at the same horizontal distance belong to the same “vertical line”.
- Within each vertical line, nodes are typically traversed from top to bottom (i.e., by increasing level).
- If multiple nodes fall on the same horizontal distance AND the same level (which is rare in standard binary trees, but possible), their relative order (e.g., left-to-right as in level order) is usually preserved.
3. Horizontal Distance (HD) and Level Convention
- Root Node: Assigned a Horizontal Distance (HD) of
0and Level0. - Left Child: For a node at
(HD, Level), its left child will be at(HD - 1, Level + 1). - Right Child: For a node at
(HD, Level), its right child will be at(HD + 1, Level + 1).
4. Algorithm: VerticalOrder(Node* root)
-
Core Idea: Uses Breadth-First Search (BFS) to traverse the tree. While traversing, it keeps track of each node’s horizontal distance (HD) and its level. A
mapofmap(ormapofvectorwhere custom sorting might be needed for levels) is used to store nodes, which naturally sorts them by HD and then by Level. -
Data Structures Used:
queue<pair<Node*, pair<int, int>>> Q: This queue is used for the BFS. Each element in the queue is apaircontaining:Node*: The current tree node.pair<int, int>: Another pair representing{HorizontalDistance, Level}of that node.
map<int, map<int, vector<int>>> NodeMap: This nested map is crucial for storing and sorting nodes:- Outer Map Key (
intHD): Stores nodes grouped by their horizontal distance.std::mapinherently sorts keys, ensuring vertical lines are processed from left to right (smallest HD to largest HD). - Inner Map Key (
intLevel): Stores nodes within a specific horizontal distance, grouped by their level.std::mapinherently sorts keys, ensuring nodes within a vertical line are processed from top to bottom (smallest Level to largest Level). - Innermost Value (
vector<int>): Stores thedataof nodes. Avectoris used to handle cases where multiple nodes might fall on the exact same HD and Level (though less common in a strict binary tree).
- Outer Map Key (
-
Steps:
- Handle Empty Tree: If
rootisNULL, return an empty vector. - Initialization:
- Push the
rootnode into the queueQ, along with its initial HD0and Level0:Q.push({root, {0, 0}});.
- Push the
- BFS Traversal (
while(!Q.empty())):- Dequeue the
tempelement from the front of theQ. - Extract
FrontNode(the actual tree node),HorizDist, andLvlfromtemp. - Store in
NodeMap: AddFrontNode->datato thevectorassociated with itsHorizDistandLvlinNodeMap:NodeMap[HorizDist][Lvl].push_back(FrontNode->data);. - Enqueue Children:
- If
FrontNode->leftexists: Enqueue it withHD-1andLvl+1. - If
FrontNode->rightexists: Enqueue it withHD+1andLvl+1.
- If
- Dequeue the
- Construct Final Result: After the BFS loop completes,
NodeMapholds all nodes correctly grouped and sorted.- Iterate through
NodeMap(outer map for HDs). - For each HD, iterate through its inner map (for Levels).
- For each Level, iterate through the
vectorof node data. - Add each node’s
datato theanswervector.
- Iterate through
- Return: Return the
answervector containing all node data in vertical order.
- Handle Empty Tree: If
5. Complexity Analysis
-
Time Complexity:
O(N log W + N log H)or effectivelyO(N log N)in worst case.N: Number of nodes in the tree.W: Width of the tree (number of distinct horizontal distances).H: Height of the tree (number of distinct levels).- BFS traversal itself is
O(N). - Inserting into
std::maptakesO(log K)time, whereKis the number of elements already in the map.- The outer map has
Wentries. - The inner maps have up to
Hentries. - Thus, insertions dominate:
Ninsertions intoNodeMapwhich involveslog Wfor outer map andlog Hfor inner map lookup/insertion on average.
- The outer map has
- Iterating through the map at the end is
O(N)because it visits each stored node once. - Overall,
O(N log W)if levels within a column are just appended to vector and not sorted, but withmap<int, map<int, vector<int>>>it’sO(N log W + N log H). SinceWandHcan beO(N)in worst-case (skewed tree), it can beO(N log N).
-
Space Complexity:
O(N)Q(queue) can store up toO(W)nodes.NodeMapstores allNnodes. In the worst case (a skewed tree),NodeMapmight haveNdistinct horizontal distances, each containing one node.answervector storesO(N)elements.- Therefore, the space complexity is dominated by storing all nodes in
NodeMapandanswer, leading toO(N).