二叉树先根(先序)遍历的改进_C 语言

二叉树的特点:每个结点的度最大不能超过2,并且左右子树不能颠倒

二叉树的存储结构:下面采用链式存储进行阐述,堆排序算法(快速排序改进)采用的顺序存储结构的二叉树,先看如下结构体的存储方式

顺序存储:

复制代码 代码如下:

/*二叉树的顺序存储*/
#define  MAX_TREE_SIZE 100
typedef  TElemType  SqBiTree[MAX_TREE_SIZE];

链式存储:

复制代码 代码如下:

/*二叉树的链式存储*/
typedef struct BiTNode
{
 TElemType data;
 BiTNode  *lchild,*rchild;
}
BiTNode, *BiTree;

这里的TElemType的类型如下,这里我使用了int型的定义:

复制代码 代码如下:

#define INT_TYPE
#ifdef INT_TYPE
typedef int TElemType;
#elif defined FLOAT_TYPE
typedef float TElemType
#elif defined STRING_TYPE
typedef char  *TElemType
#endif

二叉树的创建:这里需要进行递归创建,如下

复制代码 代码如下:

int CreateBiTree(BiTree &T)
{
 int nData;

 printf("Please Enter BiTree Node data:\n"); 
 scanf_s("%d", &nData);

 if (nData == 0)
 {
  T = NULL;
  return OK;
 }
 else if (nData > 0 && nData < 100)
 {
  T = (BiTNode*)malloc(sizeof(BiTNode));
  if (!T)
  {
   return BTOVERFLOW;
  }
  T->data = nData;
  CreateBiTree(T->lchild);
  CreateBiTree(T->rchild);
  return OK;
 }
#ifdef _DEBUG
 printf("Enter data Error!\n");
#endif // _DEBUG

 return ERROR;
}

这里我对数据进行了限制,便于进行测试,这里只接受0~100的数据,如果是0表明当前没有孩子的节点(左孩子或者右孩子),如果存在就创建节点,填充数据
遍历二叉树:创建后之后,我必须测试创建的二叉树中的数据是否正确,这里采用的是先根遍历,如下

复制代码 代码如下:

/*遍历二叉树*/
int PreOrderTraverse(BiTree T, int (*VisitNode)(TElemType))
{
 if (T)
 {
  if (VisitNode(T->data))
  {
   if (PreOrderTraverse(T->lchild, VisitNode))
   {
    if (PreOrderTraverse(T->rchild, VisitNode))
    {
     return OK;
    }
   }
  }
  return ERROR;
 }
 return OK; //如果没有子孩子,这时候应该回溯,要查看右孩子必须为真
}

这里遍历的时候采用了一个函数,注意传递的形参是函数指针,只是进行简单的结点数据的输出,如下:

复制代码 代码如下:

int VisitNode(TElemType data)
{
#if defined(INT_TYPE) || defined(FLOAT_TYPE)
 printf("%d ", data);
#elif defined(STRING_TYPE)
 printf("%s ", data);
#endif
 return OK;
}

但是在遍历的时候,为什么T为NULL的时候,返回还是OK(1)呢,这里主要是上面的遍历函数的原因,因为这里必须是先遍历左孩子且返回值为真,才能遍历右孩子,所以不能返回ERROR(0),感觉返回值有点怪,修改如下

复制代码 代码如下:

int PreOrderTraverseEx(BiTree T, int (*VisitNode)(TElemType))
{
 if (T)
 {
  if (VisitNode(T->data))
  {
   PreOrderTraverse(T->lchild, VisitNode);
   PreOrderTraverse(T->rchild, VisitNode);
   return OK;
  }
 }
 return ERROR; //如果没有子孩子,这时候应该回溯
}

这样看着就舒服多了,其实可以不使用任何返回值,主要遍历完左右子树不用做其他任何事情,如果还有其他,就不能没有返回值,这里return OK其实要不要也无所谓,因为我根本没有进行判断
测试用例:如下

复制代码 代码如下:

 BiTree T;
 if (CreateBiTree(T))
 {
  PreOrderTraverseEx(T, VisitNode);
  printf("\n");
 }

这里对测试的数据输入其实有一定的要求,假设根为12 孩子结点为 34 78,这里应该这样输入数据 12 34 0 0 78 0 0,只有这样才能正常退出,如下测试结果:
Please Enter BiTree Node data:
12
Please Enter BiTree Node data:
34
Please Enter BiTree Node data:
0
Please Enter BiTree Node data:
0
Please Enter BiTree Node data:
78
Please Enter BiTree Node data:
0
Please Enter BiTree Node data:
0
12 34 78

从前面我可以看到这里采用的其实都是递归算法,我们都知道递归最大之弊病就是在每次下潜下一层的时候,一定要保存当前所在层次的数据,具体哪些数据其实是由操作系统OS来进行管理的,但是像每次的形参T一定会入栈,便于在层次退出返回上一层的时候使用,所以这里就可以采用非递归的方式的来进行修改算法:如何做呢?

请参考二叉树先序遍历的非递归算法

时间: 2024-09-30 23:46:57

二叉树先根(先序)遍历的改进_C 语言的相关文章

c语言版本二叉树基本操作示例(先序 递归 非递归)_C 语言

复制代码 代码如下: 请按先序遍历输入二叉树元素(每个结点一个字符,空结点为'='):ABD==E==CF==G== 先序递归遍历:A B D E C F G中序递归遍历:D B E A F C G后序递归遍历:D E B F G C A层序递归遍历:ABCDEFG先序非递归遍历:A B D E C F G中序非递归遍历:D B E A F C G后序非递归遍历:D E B F G C A深度:请按任意键继续. . . 复制代码 代码如下: #include<stdio.h>#include&

UVa 548:Tree 二叉树的重建——中序遍历与后续遍历进行建树

题目链接: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=104&page=show_problem&problem=489 题目类型: 数据结构, 二叉树 题目大意: 给两个组数字,都是在同一棵二叉树上的,第一组是按中序遍历(inorder)顺序输出的,第二组是按后序遍历(postorder)输出的, 根据这两组数据构建出原来的二叉树,然后计算从根结点到每个叶子结

二叉树的应用-先序遍历中序遍历还原二叉树

二叉树的一些应用 还是大实验要求的 还有已知先序遍历 中序遍历求后续遍历 #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAX 100 //节点个数 #define Null 0 typedef int Elemtype; class node { public: Elemtype data; no

C语言二叉树的非递归遍历实例分析_C 语言

本文以实例形式讲述了C语言实现二叉树的非递归遍历方法.是数据结构与算法设计中常用的技巧.分享给大家供大家参考.具体方法如下: 先序遍历: void preOrder(Node *p) //非递归 { if(!p) return; stack<Node*> s; Node *t; s.push(p); while(!s.empty()) { t=s.top(); printf("%d\n",t->data); s.pop(); if(t->right) s.pus

使用C语言求二叉树结点的最低公共祖先的方法_C 语言

算法分析 我们直接来分析O(n)的算法. 比如求节点F和节点H的最低公共祖先,先求出从根节点A到F的路径,再求出A到H的路径,那么最后一个相同的节点就是最低公共祖先.A->B->D->F和A->B->E->H,最后相同的节点事B,所以最低公共祖先是B节点.求根节点到指定节点的算法先前已经更新过了,复杂度是O(n),所以总的时间复杂度是O(n). 条件细化: (1)树如果是二叉树,而且是二叉排序树.              这中条件下可以使用二叉排序树的搜索功能找到最低

C++实现哈夫曼树简单创建与遍历的方法_C 语言

本文以实例形式讲述了C++实现哈夫曼树简单创建与遍历的方法,比较经典的C++算法. 本例实现的功能为:给定n个带权的节点,如何构造一棵n个带有给定权值的叶节点的二叉树,使其带全路径长度WPL最小. 据此构造出最优树算法如下: 哈夫曼算法: 1. 将n个权值分别为w1,w2,w3,....wn-1,wn的节点按权值递增排序,将每个权值作为一棵二叉树.构成n棵二叉树森林F={T1,T2,T3,T4,...Tn},其中每个二叉树都只有一个权值,其左右字数为空 2. 在森林F中选取根节点权值最小二叉树,

基于大端法、小端法以及网络字节序的深入理解_C 语言

关于字节序(大端法.小端法)的定义<UNXI网络编程>定义:术语"小端"和"大端"表示多字节值的哪一端(小端或大端)存储在该值的起始地址.小端存在起始地址,即是小端字节序:大端存在起始地址,即是大端字节序. 也可以说: 1.小端法(Little-Endian)就是低位字节排放在内存的低地址端即该值的起始地址,高位字节排放在内存的高地址端. 2.大端法(Big-Endian)就是高位字节排放在内存的低地址端即该值的起始地址,低位字节排放在内存的高地址端.举

堆排序算法(选择排序改进)_C 语言

首先要理解堆的含义:要么所有节点都不大于其子孩子节点数据,要么都不小于其子孩子节点数据 堆排序的核心思想:就是要满足所有节点都满足上面两点,如何完成,看下面 堆排序的步骤: 1.首先要建成一个大顶堆或者小顶堆,在建的过程中其实就是调整节点的位置,首先要从最后最后一个节点的母亲节点开始,按照堆的含义调整.为什么不是最后一个或者其他?因为要保证完整性和不必要性,所以只需从最后一个的母亲节点开始即可(下面的堆默认存在顺序结构,从索引0开始的,所以有些二叉树的特性请查阅二叉树),直至索引节点为0的节点.

C++实现图的邻接表存储和广度优先遍历实例分析_C 语言

本文实例讲述了C++实现图的邻接表存储和广度优先遍历方法.分享给大家供大家参考.具体如下: 示例:建立如图所示的无向图 由上图知,该图有5个顶点,分别为a,b,c,d,e,有6条边. 示例输入(按照这个格式输入): 5 6 abcde 0 1 0 2 0 3 2 3 2 4 1 4 输入结束(此行不必输入) 注:0 1表示该图的第0个顶点和第1个定点有边相连,如上图中的a->b所示       0 2表示该图的第0个顶点和第2个定点有边相连,如上图中的a->c所示       2 3表示该图的