树的常见遍历大体分为:深度优先遍历(DFS)与广度优先遍历(BFS)。
深度优先遍历又分为先根遍历(DLR),中根遍历(LDR),后跟遍历(LRD),这里举一个例子比如如下二叉树:
深度优先遍历的结果:
先根遍历:ABDECFG
中根遍历:DBEAFCG
后跟遍历:DEBFGCA
广度优先遍历的结果:ABCDEFG
具体实现可分为递归与非递归两种方式,递归较为简单这里主要谈谈非递归方式,对于深度优先算法而言多采用栈的形式,利用两层while循环实现,内层while循环主要将每个节点的左子树压入栈内直找到叶节点停止,而后依据不同的策略进行输出,这里稍微需要注意后根遍历当中,每个节点压入栈的同时需要保存一个标志位用来说明是否已经访问了该节点的右孩子节点,如果没有访问则进行压栈操作并置标志位,如果已经访问则输出节点信息并且执行弹栈操作。而广度优先采用队列方式实现,具体实现比较简单不再赘述,代码如下:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
// recursion
void DLR(TreeNode *root){
if(root != NULL){
cout << root->val << " ";
DLR(root->left);
DLR(root->right);
}
}
void LDR(TreeNode *root){
if(root != NULL){
LDR(root->left);
cout << root->val << " ";
LDR(root->right);
}
}
void LRD(TreeNode *root){
if(root != NULL){
LRD(root->left);
LRD(root->right);
cout << root->val << " ";
}
}
// non-recursion
void non_DLR(TreeNode *root){
stack<TreeNode *> address;
TreeNode *temp = root;
while(address.size() != 0 || temp != NULL){
while(temp != NULL){
cout << temp->val << " ";
address.push(temp);
temp = temp->left;
}
temp = address.top();
address.pop();
temp = temp->right;
}
cout << endl;
}
void non_LDR(TreeNode *root){
stack<TreeNode *> address;
TreeNode *temp = root;
while(address.size() != 0 || temp != NULL){
while(temp != NULL){
address.push(temp);
temp = temp->left;
}
temp = address.top();
address.pop();
cout << temp->val << " ";
temp = temp->right;
}
cout << endl;
}
void non_LRD(TreeNode *root){
stack<pair<TreeNode *, int>> address;
TreeNode *temp = root;
while(address.size() != 0 || temp != NULL){
while(temp != NULL){
address.push(pair<TreeNode *, int>(temp, 1));
temp = temp->left;
}
temp = address.top().first;
int flag = address.top().second;
if(flag){
address.pop();
address.push(pair<TreeNode *, int>(temp, 0));
temp = temp->right;
}else{
cout << temp->val << " ";
address.pop();
temp = NULL;
}
}
cout << endl;
}
void BFS(TreeNode *root){
queue<TreeNode *> address;
address.push(root);
TreeNode *temp = NULL;
while(address.size() != 0){
temp = address.front();
address.pop();
cout << temp->val << " ";
if(temp->left != NULL){
address.push(temp->left);
}
if(temp->right != NULL){
address.push(temp->right);
}
}
cout << endl;
}