Chinaunix首页 | 论坛 | 博客
  • 博客访问: 496247
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1916
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-11 22:01
个人简介

从事实时计算多年,熟悉jstorm/spark/flink/kafka/rocketMq, 热衷于开源,希望在这里和前辈们一起学习与分享,得到长足的进步!邮箱:hustfxj@gmail.com 我的githup地址是:https://github.com/hustfxj。欢迎和大家一起交流探讨问题。

文章分类

全部博文(80)

文章存档

2017年(11)

2015年(3)

2014年(33)

2013年(33)

分类: C/C++

2013-10-29 17:03:17

1、o(n)时间遍历二叉树的递归方法


点击(此处)折叠或打开

  1. TREE-PRINT(T)
  2. 1 print key[T]
  3. 2 if left[T] != NIL
  4. 3 TREE-PRINT(left[T])
  5. 4 if right[T] != NIL
  6. 5 TREE-PRINT(right[T])

2、o(n)时间非递归遍历二叉树,借用了栈作为辅助结构


点击(此处)折叠或打开

  1. //把x结点压入栈S的顶部
  2. void Push(node *S, node x)
  3. {
  4.     S[0].key++;
  5.     S[S[0].key] = x;
  6. }
  7. //弹出栈顶元素并返回
  8. node* Pop(node *S)
  9. {
  10.     if(S[0].key == 0)
  11.         return NULL;
  12.     node *ret = &S[S[0].key];
  13.     S[0].key--;
  14.     return ret;
  15. }
  16. //用非递归的方式遍历二叉树
  17. void Tree_Print2(tree *T)
  18. {
  19.     //这种方式要借助一个栈来实现,栈的大小为树的深度
  20.     node Stack[15] = {0};//简单的数组栈,Stack[0]存储栈顶位置
  21.     node *t = T->root;
  22.     //当处理一个结点时,做如下处理
  23.     while(1)
  24.     {
  25.         //访问这个结点
  26.         cout<<t->key<<' ';
  27.         //入栈
  28.         Push(Stack, *t);
  29.         //如果有左孩子,下一步处理其左孩子
  30.         if(t->left)
  31.             t = t->left;
  32.         //如果没有左孩子
  33.         else
  34.         {
  35.             do{
  36.                 //弹出栈顶元素
  37.                 t = Pop(Stack);
  38.                 //若栈中元素已经全部弹出,那么二叉树访问结束了
  39.                 if(t == NULL)
  40.                 {
  41.                     cout<<endl;
  42.                     return;
  43.                 }
  44.             }
  45.             //如果这个栈顶元素没有右孩子,则继续出栈,直到访问结束或找到一个有右孩子的元素
  46.             while(t->right == NULL);
  47.             //如果这个栈顶元素有右孩子,则访问其右孩子
  48.             t = t->right;
  49.         }
  50.     }
  51. }


3、 O(n)时间非递归遍历二叉树

采用类似中序遍历的处理方法,对一个结点,可以分为以下几种情况

1.从父结点进入子结点进行处理

(1)如果有左孩子,就处理左孩子

(2)返回到自己

(3)访问自己

(4)如果有右孩子,就处理右孩子

(5)返回到自己的父结点

2.从左孩子返回,说明左孩子已经处理过,自己还没访问,自己的右孩子也没有处理过,就进行1-(2)

3.从右孩子返回,说明左右孩子都已经处理,自己也访问过,就返回到更上层

4.返回到根结点时,遍历结束

点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3.   
  4. /********10.4-5****************************************************************/
  5. //二叉树结点
  6. struct node
  7. {
  8.     int key;//
  9.     node *left;//指向左孩子
  10.     node *right;//指向右孩子
  11.     node *parent;//指向父结点
  12.     node(){}//构造函数
  13.     node(int x):key(x),left(NULL),right(NULL){}
  14. };
  15. //二叉树
  16. struct tree
  17. {
  18.     node *root;
  19.     tree():root(NULL){}
  20. };
  21. //遍历并输出
  22. void Tree_Print(tree *T)
  23. {
  24.     node *t = T->root;
  25.     //t指向当前处理的结点
  26.     while(t)
  27.     {
  28.         //(1)如果当前结点有左孩子,则先处理其左孩子
  29.         if(t->left)
  30.         {
  31.             t = t->left;
  32.             continue;
  33.         }
  34.         //如果当前结点没有左孩子,就访问自己并处理其左孩子
  35.         else
  36.         {
  37.             //(3)访问自己
  38.             cout<<t->key<<' ';
  39.             //(4)如果当前结点有右孩子,则处理其右孩子
  40.             if(t->right)
  41.             {
  42.                 t = t->right;
  43.                 continue;
  44.             }
  45.             //(5)如果结点既没有左孩子,又没有右孩子
  46.             //向上找,找到下一个待处理的点,过程类似于中序遍历
  47.             //下一个待处理的点的特点是:有右孩子且右孩子还未处理过,下一个待处理的就是这个右孩子
  48.             while(1)
  49.             {
  50.                 //如果当前孩子是其父结点的左孩子,说明其父结点及父结点的右孩子还没有处理过
  51.                 //t->parent满足条件1.未访问过2.有右孩子3.其右孩子没处理过,于是处理其右孩子
  52.                 if(t == t->parent->left && t->parent->right)
  53.                 {
  54.                     //父结点还没有访问过,先访问父结点,再处理父结点的右孩子
  55.                     cout<<t->parent->key<<' ';
  56.                     t = t->parent->right;
  57.                     break;
  58.                 }
  59.                 //t->parent满足条件1.未访问过2.元右孩子
  60.                 if(t == t->parent->left && t->parent->right == NULL)
  61.                     //访问父结点,并继续向上寻找
  62.                     cout<<t->parent->key<<' ';
  63.                 //t->parent满足条件1.访问过2.如果有右孩子,一定已经处理过了,所以不考虑
  64.                 //继续向上寻找
  65.                 t = t->parent;
  66.                 //一直找到根结点也没有找到符合要求的结点,那么二叉树已经遍历完成
  67.                 if(t == T->root)
  68.                 {
  69.                     cout<<endl;
  70.                     return;
  71.                 }
  72.             }
  73.         }
  74.     }
  75. }
  76. /*input:0=NIL
  77. 12 7 3
  78. 15 8 0
  79. 4 10 0
  80. 10 5 9
  81. 2 0 0
  82. 18 1 4
  83. 7 0 0
  84. 14 6 2
  85. 21 0 0
  86. 5 0 0
  87. */
  88. int main()
  89. {
  90.     //构造一棵树按照10.4-1
  91.     int i;
  92.     node A[11];//这个数组仅仅用于构造10.4-1中的树,在遍历时不使用
  93.     for(i = 1; i <= 10; i++)
  94.     {
  95.         int key, left, right;
  96.         cin>>key>>left>>right;
  97.         A[i].key = key;
  98.         if(left)
  99.         {
  100.             A[i].left = &A[left];
  101.             A[left].parent = &A[i];
  102.         }
  103.         else A[i].left = NULL;
  104.         if(right)
  105.         {
  106.             A[i].right = &A[right];
  107.             A[right].parent = &A[i];
  108.         }
  109.         else A[i].right = NULL;
  110.     }
  111.     //生成一棵树
  112.     tree *T = new tree();
  113.     T->root = &A[6];
  114.     //10.4-5
  115.     Tree_Print(T);
  116.     return 0;
  117. }

 

阅读(1543) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~