/* * 时间:2015年5月4日09:58:21 * 目的:实现二叉树的先序遍历递归。 * 总结和思考!二叉树一般使用链式存储结构 * 如果使用顺序存储方式,除非二叉树是完全二叉树或者满二叉树 * 否则会浪费很多内存空间! */ # include <stdio.h> typedef struct Node{ char data; //数据元素 Node *LChild; //左孩子节点 Node *RChild; //右孩子节点 }BTree; /*递归算法--先序遍历*/ //二叉树的创建,使用先序算法,先序遍历算法:先根后左再右的遍历顺序。 void CreateTree(BTree **tNode) { char element; scanf("%c",&element); //#表示空结点 if(element == '#') (*tNode) = NULL; else { /* 创建一个树结点,这个new对象就是为什么要使用二级指针的原因.要保证地址不会丢失。 * 那么我们来分析,假如我们不用二级指针,而是像前面使用一级指针,那么在main()函数 * 中传递了tree的地址,相当于tNode指向了tree地址,这就是我们的初衷,但是我们使用 * tNode = new Node;给树的节点指针分配内存空间,这样就导致tNode指向了新的Node地址 * 所以你的一切跟tNode操作都跟tree无关,所以就会导致错误!刚开始我也不是很理解为什么要 * 用二级指针,但是通过理解我慢慢体会到这个重要性,或者你嫌二级指针麻烦,你也可以吧BTree * 定义成结构体指针*BTree,这样你就可以直接使用Btree *tNode。方法自己来选,个人认为二级指针 * 虽然麻烦,但是可以更加有助于理解。 */ (*tNode) = new Node; //创建根节点 (*tNode)->data = element; //给根节点的数据元素项赋值 /*其实在写这个程序之前,我不是很理解递归内部工作机制,我只是知道递归内部是使用栈来进行操作的 * 所以在下一篇文章中先序的非递归创建二叉树和非递归遍历二叉树会使用到栈的知识。 */ /*下面这种方法明显是递归的方式,但是我们好好想一想那么递归结束的条件是什么,是不是叶子节点的 * 左右子树全部为NULL,本来我不是很理解既然这里使用到了递归,那么这个算法结束的条件是什么? * 大家可以想象一下叶子节点作为根节点后,它是不是也要进行CreateTree(&(*tNode)->LChild); * CreateTree(&(*tNode)->RChild);这2个方法,然后我们输入了#表示左右子树都为空,这样我们就不会运行 * else中的代码了,所以大家记住,这个递归算法结束的条件就是叶子节点的左右孩子都为空(#) */ CreateTree(&(*tNode)->LChild); //创建左子树,这是使用递归的方式 CreateTree(&(*tNode)->RChild); //创建右子树 } } /* 输出函数(访问根节点) * 经常听一些视频,每次都说访问根节点,刚开始我不是很理解 * 什么叫做访问,说白了不就是printf(),自己输出data值,所以一些理论 * 知识真是坑害了好多人啊。 */ void visit(BTree **tNode) { if((*tNode)->data != '#') printf("%c ",(*tNode)->data); } //先序遍历 void preOrder(BTree **tNode) { /* (*tNode) != NULL也是递归结束的标志语 */ if((*tNode) != NULL) { //访问根结点 visit(tNode); //访问左子结点 preOrder(&(*tNode)->LChild); //访问右结点 preOrder(&(*tNode)->RChild); } } int main() { BTree *tree; printf("递归--创建一个二叉树,'#'表示空结点\n"); CreateTree(&tree); printf("<先序遍历-递归算法:>\n"); preOrder(&tree); printf("\n"); return 0; }
时间: 2024-10-10 09:03:27