PS:树型结构是一种重要的非线性数据结构,教科书上通常都是树与二叉树,因而可知,树和二叉树是有区别和联系的,网上有人说二叉树是树的一种特殊形式,但通过查资料,树和二叉树没有一个确定的说法,但惟一能够确定都是树型结构。可是按照定义来看二叉树并非树的一种特殊形式(下面解释)。树型数据结构的做用能够表示数据元素之间一对多的关系,一个公司里的各个部门均可以用树形来表示。算法
(1)彻底二叉树 ——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,而且叶子结点都是从左到右依次排布,这就是彻底二叉树。数据结构
(2)满二叉树 ——除了叶结点外每个结点都有左右子叶且叶子结点都处在最底层的二叉树。函数
(3)平衡二叉树——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具备如下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,而且左右两个子树都是一棵平衡二叉树。测试
/*
刘志通
**/
typedef struct twoCha { char data; struct twoCha *Lchild, *Rchild;//左右孩子结点 } twoCha, *twoChaL;
当咱们在键盘上敲了一行的char类型数据,能够按照必定的结构储存在计算机上,就要写一个算法,二叉树分左右孩子,因此,若是没有左(右)孩子就输入一个空格或者#,表明空。若是有左(右)孩子就新建一个结点,来存放该结点的数据data。ui
int createTwo(twoChaL &tL) { char ch; scanf("%c",&ch); if (ch == '#') { tL = NULL; return 0; } else { tL= (twoChaL)malloc(sizeof(twoCha)); if (tL == NULL) { printf("错误tl=NULL\n"); return 0; } else { tL->data = ch; createTwo(tL->Lchild); createTwo(tL->Rchild); } } return 0; }
画的很差,凑活着看吧。spa
咱们以这个二叉树为例子,来分析他的遍历形式,遍历分为三种code
void diGuiBianLi(twoChaL &tL,int xl) { if (tL == NULL) { return; } else { if(xl == 1){ //先序遍历 printf("%c ",tL->data); diGuiBianLi(tL->Lchild,xl); diGuiBianLi(tL->Rchild,xl); }else if(xl == 2){ //中序遍历 diGuiBianLi(tL->Lchild,xl); printf("%c ",tL->data); diGuiBianLi(tL->Rchild,xl); } else if(xl == 3){ //后序遍历 diGuiBianLi(tL->Lchild,xl); diGuiBianLi(tL->Rchild,xl); printf("%c ",tL->data); } } }
递归的代码很是少,可是一开始接触 理解起来仍是比较难的,固然,你一旦理解后,那就很是简单了。递归的思想就是把一个大问题分红多个相似的小问题解决。blog
方法:查找一个结点没有左右孩子,就是叶子结点。能够定义一个static int count变量,若是该结点没有左右结点那么就让count++;排序
int leafCount(twoChaL &tL) { static int count; if (tL != NULL) { if (tL->Lchild == NULL && tL->Rchild == NULL) { count++; } leafCount(tL->Lchild); leafCount(tL->Rchild); } return count; }
方法:看结点的左孩子和右孩子哪个更长,当深刻到最低结点时,左右孩子比较,谁大谁加一(相等左孩子加一)。递归
int treeDeep(twoChaL &tL) { int deep = 0; if (tL != NULL) { int leftdeep = treeDeep(tL->Lchild); int rightdeep = treeDeep(tL->Rchild); deep = leftdeep >= rightdeep?leftdeep+1:rightdeep+1; } return deep; }
这里以中序为例,利用栈的知识点(顺序栈),首先把根节点进栈,而后依次左孩子进栈,直到左孩子为NULL时结束,可是NULL也是入栈的,而后再把NULL出栈,下一步就是把栈顶元素取出并打印,再把该栈顶元素的右孩子进栈,无论右孩子是否是NULL都要入栈,入栈以前把栈顶元素弹栈。
定义栈的data域,要用结点的结构体
int top = -1; //栈 void push(twoChaL *a,twoChaL elem){ a[++top]=elem; } //弹栈函数 void pop(){ if (top==-1) { return ; } top--; } //拿到栈顶元素 twoChaL getTop(twoChaL *a){ return a[top]; } void zhongXu2(twoChaL Tree){ //顺序栈 twoChaL a[100]; twoChaL p; push(a, Tree);//根结点进栈 while (top!=-1) {//top!=-1说明栈内不为空 while ((p=getTop(a)) &&p){//取栈顶元素,且不能为NULL push(a, p->Lchild);//将该结点的左孩子进栈,若是没有左孩子,NULL进栈 } pop();//跳出循环,栈顶元素确定为NULL,将NULL弹栈 /* //测试数据,主要观察栈中NULL出栈后,还有什么在栈中(栈顶), if(a[top]){ printf(" 跳出循环 %c\n",a[top]->data); }*/ if (top!=-1) { p=getTop(a);//取栈顶元素 pop();//栈顶元素弹栈 printf("%c ",p->data); push(a, p->Rchild);//将p指向的结点的右孩子进栈 } } }
讨论群