二叉树遍历

二叉树表示

二叉树的二叉链表表示

 1#include <cstdio>
 2#include <queue>
 3#include <stack>
 4#define ElemType int
 5#define EndTag 0
 6using namespace std;
 7
 8// 二叉树的链式存储
 9typedef struct Node{
10 ElemType data;
11 struct Node *left, *right;
12} Node, *BinTree;

二叉树的创建

 1// 初始化二叉树
 2void InitTree(BinTree &T){
 3 T = new Node;
 4 if(T == NULL)
 5  return;
 6 T->left = T->right = NULL;
 7}
 8
 9// 从文件输入流创建二叉树(前序遍历建立)
10void CreateTree(BinTree &T, istream &in)
11{
12 ElemType e;
13 if(in.peek() != EOF)
14 {
15  in >> e;
16  if(e == EndTag)
17   T = NULL;
18  else{
19   T = new Node;T->data = e;
20   T->left = T->right = NULL;
21   CreateTree(T->left, in);
22   CreateTree(T->right, in);
23  }
24 }
25}

二叉树遍历

前序遍历

前序递归遍历

 1// 二叉树前序递归遍历
 2void PreOrder(BinTree &T)
 3{
 4 if(T)
 5 {
 6  printf("%d ", T->data);
 7  PreOrder(T->left);
 8  PreOrder(T->right);
 9 }
10}

前序非递归遍历

 1// 二叉树前序非递归遍历
 2void PreOrder_NR(BinTree &T)
 3{
 4 if(T == NULL)
 5  return;
 6 stack<Node *> S;
 7 S.push(T); Node *cur;
 8 while(!S.empty())
 9 {
10  cur = S.top(); S.pop();
11  printf("%d ", cur->data);
12  if(cur->right != NULL)
13   S.push(cur->right);
14  if(cur->left != NULL)
15   S.push(cur->left);
16 }
17}

中序遍历

中序递归遍历

 1// 二叉树中序递归遍历
 2void InOrder(BinTree &T)
 3{
 4 if(T)
 5 {
 6  InOrder(T->left);
 7  printf("%d ", T->data);
 8  InOrder(T->right);
 9 }
10}

中序非递归遍历

 1// 二叉树中序非递归遍历
 2void InOrder_NR(BinTree &T)
 3{
 4 stack<Node *> S;
 5 Node *cur = T;
 6 while(cur != NULL || !S.empty())
 7 {
 8  // 将左子女链上结点全部压栈
 9  while(cur != NULL)
10  {
11   S.push(cur);
12   cur = cur->left;
13  }
14  cur = S.top(); S.pop(); 
15  printf("%d ", cur->data); 
16  cur = cur->right; 
17 } 
18}

后序遍历

后序递归遍历

 1// 二叉树后序递归遍历
 2void PostOrder(BinTree &T)
 3{
 4 if(T)
 5 {
 6  PostOrder(T->left);
 7  PostOrder(T->right);
 8  printf("%d ", T->data);
 9 }
10}

后序非递归遍历

前驱指针法
 1// 二叉树后序非递归遍历(附加前驱指针法)
 2void PostOrder_NR(BinTree &T)
 3{
 4 if(!T)
 5  return;
 6 stack<Node *> S; S.push(T);
 7 Node *cur, *pre = NULL; // 当前指针cur和后序前驱指针pre
 8 while(!S.empty())
 9 {
10  cur = S.top();
11  if(!cur->left && !cur->right)
12  {
13   // 当前结点两个子树都为空
14   S.pop(); printf("%d ", cur->data); 
15   pre = cur;
16  }else if(pre && (cur->left == pre || cur->right == pre)){
17   // 当前结点存在子树不为空,但已被访问过
18   S.pop(); printf("%d ", cur->data); 
19   pre = cur;
20  }else{
21   // 当前结点存在子树不为空,并且没有被访问过
22   if(cur->right)
23    S.push(cur->right); // 右子女不为空,则先将右子女压栈
24   if(cur->left)
25    S.push(cur->left); // 左子女不为空,则将左子女压栈
26  } 
27 }
28}
重复入栈法
 1// 二叉树后序非递归遍历(重复入栈法)
 2void PostOrder_NR2(BinTree &T)
 3{
 4 if(!T)
 5  return;
 6 stack<Node *> S; S.push(T); S.push(T);
 7 Node *cur;
 8 while(!S.empty())
 9 {
10  cur = S.top(); S.pop();
11  if(!S.empty() && cur == S.top())
12  {
13   // 栈不空并且cur是第一次被访问
14   if(cur->right)
15   {
16    S.push(cur->right); S.push(cur->right);
17   }
18   if(cur->left)
19   {
20    S.push(cur->left); S.push(cur->left);
21   }
22  }else
23   printf("%d ", cur->data);
24 }
25}
附加标志法
1enum Tag{L,R};
2
3// 附加标志tag用于后序非递归遍历
4typedef struct Node{
5 ElemType data;
6 struct Node *left, *right;
7 Tag tag; // 后序非递归遍历的标志位
8} Node, *BinTree;
 1// 二叉树后序非递归遍历(附加tag标志法)
 2void PostOrder_NR3(BinTree &T)
 3{
 4 stack<Node*> S;
 5 Node *cur = T, *temp; 
 6 while(cur || !S.empty())
 7 {
 8  while(cur)
 9  {
10   cur->tag = L;
11   S.push(cur);
12   cur = cur->left;
13  }
14  if(!S.empty())
15  {
16   temp = S.top();
17   if(temp->tag == L)
18   {
19    temp->tag = R;
20    cur = temp->right;
21   }else{
22    S.pop();
23    printf("%d ", temp->data);
24   }
25  }
26 }
27
28}

层次序遍历

 1// 层次序遍历
 2void LevelOrder(BinTree &T)
 3{
 4 if(!T)
 5  return;
 6 queue<Node *> Q;
 7 Q.push(T); Node *cur;
 8 while(!Q.empty())
 9 {
10  cur = Q.front(); Q.pop();
11  printf("%d ", cur->data);
12  if(cur->left)
13   Q.push(cur->left);
14  if(cur->right)
15   Q.push(cur->right);
16 }
17}
下一页
上一页