目录
帮助理解:浙江大学数据结构:https://www.bilibili.com/video/BV1H4411N7oD?p=33
1 先序遍历
//前序遍历
void ProOrderTraverse(BiTree tree)
{
if (tree == NULL)
return;
cout << tree->data << " ";
ProOrderTraverse(tree->lchild);
ProOrderTraverse(tree->rchild);
}
//非递归前序遍历
void ProOrder(BiTree pRoot)
{
if (pRoot == NULL)
return;
BiTree p = pRoot;
stack<BiTree>s;
while (p != NULL || !s.empty())
{
while (p != NULL)
{
s.push(p);
cout << p->data << " "; //第一次遇见的时候输出
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
s.pop();
p = p->rchild;
}
}
}
2 中序遍历
//中序遍历
void midOrderTraverse(BiTree tree)
{
if (tree == NULL)
return;
midOrderTraverse(tree->lchild);
cout << tree->data << " ";
midOrderTraverse(tree->rchild);
}
//非递归中序遍历
void midOrder(BiTree pRoot)
{
if (pRoot == NULL)
return;
BiTree p = pRoot;
stack<BiTree>s;
while (p != NULL || !s.empty())
{
while (p!=NULL)
{
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
cout << p->data << " "; //第二次遇见的时候输出
s.pop();
p = p->rchild;
}
}
}
3 后序遍历
3.1 对于后序遍历的非递归遍历,可以将先序遍历的左右顺序颠倒,逆序输出结果。(喜欢用这一种)
根→左→右 ——(颠倒左右顺序)——根→右→左——(逆序输出)——左→右→根
3.2 对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问, 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是 否是第一次出现在栈顶。
//后序遍历
void postOrderTraverse(BiTree pRoot)
{
if (pRoot == NULL)
return;
postOrderTraverse(pRoot->lchild);
postOrderTraverse(pRoot->rchild);
cout << pRoot->data<<" ";
}
//后序遍历非递归
void PostOrderNoRecursion(BiTree pRoot){
if (pRoot == NULL){
cout << "Root is NULL!" << endl;
return;
}
stack<BiTree> s1; //辅助栈
stack<BiTree> s2; //逆序记录遍历结果
BiTree p = pRoot;
while(p || !s1.empty()){
if(p){
s2.push(p);//根节点先压栈
s1.push(p);
p = p->rchild;//找右儿子
}
else{
p = s1.top();
s1.pop();
p = p->lchild;//找左儿子
}
}
//此时倒序输出stack2即为后序遍历的序列
while(!s2.empty()){
p = s2.top();
s2.pop();
cout << p->data << " ";
}
cout<<endl;
}
4 层序遍历
定义一个队列,将根节点入队。
取队首元素出队,将他的左右儿子入队。
知道队空,遍历结束。
//层序遍历
void printTree(BiTree pRoot)
{
queue<BiTree> q; //定义一个队列,数据类型是二叉树指针,不要仅是int!!不然无法遍历
q.push(pRoot);
while (!q.empty())
{
BiTree front = q.front();
cout<<front->data<<" ";
q.pop();
if(front->lchild != nullptr)
q.push(front->lchild);
if (front->rchild != nullptr)//判断最前面的右节点是否为空,不是则放入队列
q.push(front->rchild);
}
}
深度优先dfs——先序遍历
广度优先bfs——层次遍历
测试代码:
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<queue>
using namespace std;
#define len 15 //定义一个长度
typedef int ElemType;
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
typedef struct Node
{
BiTree btnode;
bool isfirst;
}Node,*node;
//向下遍历,找到节点s应该插入的位置,节点有重复时,忽略这个节点
void SearchTreeNode(BiTree &root, BiTree &s) //注意:使用引用传递
{
if (root == NULL)
return;
if (s->data > root->data)
{
if (root->rchild == NULL)
{
root->rchild = s;
return;
}
SearchTreeNode(root->rchild, s);//s值大于根节点值,未到达叶子节点,继续向右孩子遍历
}
else if (s->data < root->data)
{
if (root->lchild == NULL)
{
root->lchild = s;
return;
}
SearchTreeNode(root->lchild, s);//s值小于根节点值,未到达叶子节点,继续向左孩子遍历
}
}
//插入一个节点,树为空,插入节点即为根节点,否则找合适的位置插入
void InsertNode(BiTree &tree, BiTree &s) //注意:使用引用传递
{
if (tree == NULL)
tree = s;
else
SearchTreeNode(tree, s);
}
//二叉排序树创建,每次增加一个结点,插到现有的二叉树上去
void CreateOrderBinaryTree(BiTree &tree, int *a)
{
for (int i = 0; i < len; i++)
{
BiTree s = (BiTree)malloc(sizeof(BiTNode));
s->data = a[i];
s->lchild = NULL;
s->rchild = NULL;
InsertNode(tree, s);
}
}
//前序遍历
void ProOrderTraverse(BiTree tree)
{
if (tree == NULL)
return;
cout << tree->data << " ";
ProOrderTraverse(tree->lchild);
ProOrderTraverse(tree->rchild);
}
//非递归前序遍历
void ProOrder(BiTree pRoot)
{
if (pRoot == NULL)
return;
BiTree p = pRoot;
stack<BiTree>s;
while (p != NULL || !s.empty())
{
while (p != NULL)
{
s.push(p);
cout << p->data << " "; //第一次遇见的时候输出
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
s.pop();
p = p->rchild;
}
}
}
//中序遍历
void midOrderTraverse(BiTree tree)
{
if (tree == NULL)
return;
midOrderTraverse(tree->lchild);
cout << tree->data << " ";
midOrderTraverse(tree->rchild);
}
//非递归中序遍历
void midOrder(BiTree pRoot)
{
if (pRoot == NULL)
return;
BiTree p = pRoot;
stack<BiTree>s;
while (p != NULL || !s.empty())
{
while (p!=NULL)
{
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
cout << p->data << " "; //第二次遇见的时候输出
s.pop();
p = p->rchild;
}
}
}
//后序遍历
void postOrderTraverse(BiTree pRoot)
{
if (pRoot == NULL)
return;
postOrderTraverse(pRoot->lchild);
postOrderTraverse(pRoot->rchild);
cout << pRoot->data<<" ";
}
//非递归实现后续遍历
void postOrder(BiTree pRoot)
{
if (pRoot == NULL)
return;
stack<node>s;
BiTree p = pRoot;
node tmp;
while (p!=NULL || !s.empty())
{
while (p != NULL) //沿左子树一直往下搜索,直至出现没有左子树的结点
{
node btn = (node)malloc(sizeof(Node));
btn->btnode = p;
btn->isfirst = true;
s.push(btn);
p = p->lchild;
}
if (!s.empty())
{
tmp = s.top();
s.pop();
if (tmp->isfirst == true) //第一次出现在栈顶
{
tmp->isfirst = false;
s.push(tmp);
p = tmp->btnode->rchild;
}
else //第二次出现在栈顶
{
cout << tmp->btnode->data<<" ";
p = NULL;
}
}
}
}
void PostOrderNoRecursion(BiTree pRoot){
if (pRoot == NULL){
cout << "Root is NULL!" << endl;
return;
}
stack<BiTree> s1; //辅助栈
stack<BiTree> s2; //逆序记录遍历结果
BiTree p = pRoot;
while(p || !s1.empty()){
if(p){
s2.push(p);
s1.push(p);
p = p->rchild;
}
else{
p = s1.top();
s1.pop();
p = p->lchild;
}
}
//此时倒序输出stack2即为后序遍历的序列
while(!s2.empty()){
p = s2.top();
s2.pop();
cout << p->data << " ";
}
cout<<endl;
}
//非递归实现后续遍历
void postorder(BiTree pRoot)
{
if (pRoot == NULL)
return;
stack<BiTree>s;
BiTree cur = pRoot, pre = NULL;
s.push(pRoot);
while (!s.empty())
{
cur = s.top();
if ((cur->lchild == NULL&&cur->rchild == NULL) ||
((pre == cur->lchild || pre == cur->rchild) && pre != NULL))
{
cout << cur->data << " ";
s.pop();
pre = cur;
}
else
{
if (cur->rchild != NULL)
s.push(cur->rchild);
if (cur->lchild != NULL)
s.push(cur->lchild);
}
}
}
//层序遍历
void printTree(BiTree pRoot)
{
queue<BiTree> q; //定义一个队列,数据类型是二叉树指针,不要仅是int!!不然无法遍历
q.push(pRoot);
while (!q.empty())
{
BiTree front = q.front();
cout<<front->data<<" ";
q.pop();
if(front->lchild != nullptr)
q.push(front->lchild);
if (front->rchild != nullptr)//判断最前面的右节点是否为空,不是则放入队列
q.push(front->rchild);
}
}
int main()
{
int a[len] = { 62, 88, 58, 47, 35, 73, 51, 99, 37, 93, 23, 27, 45, 21, 12 };
//int a[] = {1,2,3,4,5};
BiTree tree = NULL;
//创建一个二叉树,并中序遍历
CreateOrderBinaryTree(tree, a);
cout << "前序遍历" << endl;
ProOrderTraverse(tree);
cout << endl;
ProOrder(tree);
cout << endl<<endl;
cout << "中序遍历" << endl;
midOrderTraverse(tree);
cout << endl;
midOrder(tree);
cout << endl<<endl;
cout << "后序遍历" << endl;
postOrderTraverse(tree);
cout << endl;
postOrder(tree);
cout << endl;
postorder(tree);
cout << endl<<endl;
cout << "后序遍历2" << endl;
PostOrderNoRecursion(tree);
cout << endl;
cout << "层序遍历" << endl;
printTree(tree);
cout << endl;
return 0;
}
测试用例:
参考:https://blog.csdn.net/happyjacob/article/details/83116702