二叉树遍历
https://blog.csdn.net/invisible_sky/article/details/80816797
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。
对于二叉树,有深度遍历和广度遍历;
深度遍历有前序、中序以及后序三种遍历方法,
广度遍历即我们平常所说的层次遍历。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁,而对于广度遍历来说,需要其他数据结构的支撑,比如队列。
四种主要的遍历思想为: 前序遍历:根结点 ---> 左子树 ---> 右子树 中序遍历:左子树---> 根结点 ---> 右子树 后序遍历:左子树 ---> 右子树 ---> 根结点 层次遍历:只需按层次遍历即可 例如,求下面二叉树的各种遍历
前序遍历:1 2 4 5 7 8 3 6 中序遍历:4 2 7 5 8 1 3 6 后序遍历:4 7 8 5 2 6 3 1 层次(广度)遍历:1 2 3 4 5 6 7 8
深度遍历 :先插入右子树,区别前序遍历。。 1 2 5 7 8 4 3 6
// test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <stack> #include <queue> using namespace std; struct BitreeNode { int data; struct BitreeNode *lchild, *rchild; }; void InitTreeNode(BitreeNode &t,int data,BitreeNode *lchild,BitreeNode *rchild) { t.data = data; t.lchild = lchild; t.rchild = rchild; } //前序 void PreOrder(BitreeNode *t) {
if(t == nullptr) {
return;
} cout << t->data << endl; PreOrder(t->lchild); PreOrder(t->rchild); } //中序 void Inorder(BitreeNode *t) { if (t != nullptr) { Inorder(t->lchild); cout << t->data << endl; Inorder(t->rchild); } } //后序 void PostOrder(BitreeNode *t) { if (t != nullptr) { PostOrder(t->lchild); PostOrder(t->rchild); cout << t->data << endl; } } //前序非递归 void PreOrder2(BitreeNode *t) { stack<BitreeNode *> s; BitreeNode *p = t; while (p != nullptr || !s.empty()) { if (p != nullptr) { cout << p->data << endl;//根 s.push(p); p = p->lchild;//左 } else { p = s.top(); p = p->rchild;//右 s.pop(); } } } //中序非递归 //使用递归的方法,依次把树的左子树进行保存,然后依次回退完成根的访问,最后访问右子树 void Inorder2(BitreeNode *t) { stack<BitreeNode*> s; BitreeNode *p = t; while (p != nullptr || !s.empty()) { if (p != nullptr) { s.push(p); p = p->lchild;//左 } else { p = s.top(); cout << p->data << endl;//根· s.pop(); p = p->rchild;//右 } } } //后序非递归 void PostOrder2(BitreeNode *t) { stack<BitreeNode *> s; BitreeNode *p = t; BitreeNode *tmp = nullptr; //tmp 指针是为了保存节点上一次访问的状态 while (p != nullptr || !s.empty()) { if (p != nullptr) { s.push(p); p = p->lchild;//左 } else { //每次取栈顶元素 //判断栈顶元素的右孩子是否为空, //如果不为空,查看之前访问的节点是不是该栈顶元素的右孩子 p = s.top(); if (p->rchild != nullptr && p->rchild != tmp) { p = p->rchild;//右 } else { cout << p->data << endl;//根 s.pop(); //每次访问节点之后,需要将缓存上一次访问的节点,并且将指针置空 tmp = p; p = nullptr; } } } } //层次遍历 void LevelOrder(BitreeNode *t) { queue<BitreeNode *> q; BitreeNode *p; q.push(t); while (!q.empty()) { p = q.front(); q.pop(); cout << p->data << endl; if (p->lchild != nullptr) q.push(p->lchild); if (p->rchild != nullptr) q.push(p->rchild); } }
// 深度遍历 :从根节点出发,沿着左子树方向进行纵向遍历,直到找到叶子节点为止。然后回溯到前一个节点,进行右子树节点的遍历,直到遍历完所有可达节点为止。
// 数据结构:栈。父节点入栈,父节点出栈,先右子节点入栈,后左子节点入栈。递归遍历全部节点即可
void DFS(BitreeNode * root) {
if(root == nullptr) {
return;
}
stack<BitreeNode *> node_stack;
node_stack.push(root);
BitreeNode * node;
while (!node_stack.empty()) {
node = node_stack.top();
cout << node->data;
node_stack.pop();
if (node->rchild != nullptr){
node_stack.push(node->rchild); //先将右子树压栈
}
if (node->lchild != nullptr) {
node_stack.push(node->lchild); //再将左子树压栈
}
}
}
//遍历是二叉树各种操作的基础 //1、已知树求结点的双亲结点:使用前、中、后序遍历 //2、求结点的孩子结点:使用前、中、后序遍历 //3、求二叉树的深度:使用层次遍历 //4、求二叉树的叶子结点个数:使用层次遍历 //5、判断两颗二叉树是否相同:依次遍历每个节点进行比较 int main() { BitreeNode t1,t2,t3,t4,t5,t6,t7; InitTreeNode(t4, 4, nullptr, nullptr); InitTreeNode(t5, 5, nullptr, nullptr); InitTreeNode(t6, 6, nullptr, nullptr); InitTreeNode(t7, 7, nullptr, nullptr); InitTreeNode(t2, 2, &t4, &t5); InitTreeNode(t3, 3, &t6, &t7); InitTreeNode(t1, 1, &t2, &t3); LevelOrder(&t1); cin.get(); return 0; }