目录
先序、中序求后序和中序、后序求先序的简单方法:根据坐标画图便可
树:1对多,其关系有祖先、双亲、兄弟、子孙等等,其属性有树、结点、路径、高度、深度
结点的度:孩子结点的个数(仅下一辈)
树的度:各结点度的最大值
树的深度:层级
二叉树:由一个根结点以及两颗互不相交的,分别称为左子树和右子树的二叉树组成。
二叉树的性质:
第i(i>=1)层上的结点最多位2^(i-1)个
深度为k(k>=1)的二叉树最多有2^k-1个结点
叶子的数目比度数为2的结点的数目多1
总结点树为各类结点之和:n=n0+n1+n2
总结点数为所有子结点树加1:n=n1+2n2+1
故得:n0=n2+1
满二叉树:深度为k(k>=1)时有2^k-1个结点的二叉树
完全二叉树:只有最下面两层有度数小于2的结点,且最下面一层的叶子结点集中在最左边的若干位置上。
具有n个结点的完全二叉树的深度为:
log2n +1 或者 log2(n+1)
二叉排序树(二叉查找树):
1)若左子树不为空,则左子树上所有结点的值均小于根结点的值。
2)若右子树不为空,则右子树上所有结点的值均小于根节点的值。
3)左右子树也为二叉排序树。
平衡二叉树(AVL树):是一种二叉查找树,当且仅当两个子树的高度差不超过1时,这个树是平衡二叉树。
红黑树:是许多二叉查找树中的一种,它能保证在最坏的情况下,基本动态集合操作时间为O(lgn).
B树, B-树,B+树:B树为磁盘或其他直接存取辅助设备设计的一种多路查找树,每个节点中关键字非降序排列,搜索时每个节点所作的不是二叉或者“两路”分支,而是根据该节点子女数的多路分支;
B-和B+是B树变种,为平衡的多路查找树。
B+树是应文件系统所需而出的一种B-树的变型树。
B+树是对B-树的改进,要求所有的信息都在叶子节点上,且叶子节点都在同一深度,而B-树的叶子节点为空,查找成功时到非叶子节点结束,查找失败时总是在叶子节点结束,叶子节点可以在任意深度。
二叉树的遍历:
btree.h:
#ifndef _BTREE_H_ #define _BTREE_H_ #include <stdio.h> #include <stdlib.h> typedef struct node{ char data; struct node *lchild,*rchild; }Btree,*pBtree; #if 1 //参数初始化二叉树 pBtree btree_create(); #else //返回值初始化二叉树 int btree_create(pBtree *B); #endif //前序遍历 void btree_preorder(pBtree t); //中序遍历 void btree_cenorder(pBtree t); //后序遍历 void btree_latorder(pBtree t); //层次遍历 int btree_levelorder(pBtree t); //释放二叉树 int btree_destory(pBtree *B); #endif
btree.c:
#include "btree.h" #if 1 pBtree btree_create() { pBtree ta = malloc(sizeof(Btree)); pBtree tb = malloc(sizeof(Btree)); pBtree tc = malloc(sizeof(Btree)); pBtree td = malloc(sizeof(Btree)); pBtree te = malloc(sizeof(Btree)); pBtree tf = malloc(sizeof(Btree)); pBtree tg = malloc(sizeof(Btree)); pBtree th = malloc(sizeof(Btree)); ta->data = 'A'; tb->data = 'B'; tc->data = 'C'; td->data = 'D'; te->data = 'E'; tf->data = 'F'; tg->data = 'G'; th->data = 'H'; ta->lchild = tb; ta->rchild = te; tb->lchild = NULL; tb->rchild = tc; tc->lchild = td; tc->rchild = NULL; td->lchild = NULL; td->rchild = NULL; te->lchild = NULL; te->rchild = tf; tf->lchild = tg; tf->rchild = NULL; tg->lchild = th; tg->rchild = NULL; th->lchild = NULL; th->rchild = NULL; return ta; } #else int btree_create(pBtree *B) { char ch; scanf("%c",&ch); //'#'为结束标志 if('#' == ch) return -1; *B = malloc(sizeof(Btree)); if(NULL == *B) exit(0); (*B)->data = ch; //递归创建左右孩子 btree_create(&((*B)->lchild)); btree_create(&((*B)->rchild)); return 0; } #endif //先序遍历 void btree_preorder(pBtree t) { if(NULL == t) return; //第一次经过就打印其数据 printf("%c\n",t->data); //再遍历左孩子 btree_preorder(t->lchild); //最后遍历右孩子 btree_preorder(t->rchild); } //中序遍历 void btree_cenorder(pBtree t) { if(NULL == t) return; btree_cenorder(t->lchild); printf("%c\n",t->data); btree_cenorder(t->rchild); } //后序遍历 void btree_latorder(pBtree t) { if(NULL == t) return; btree_cenorder(t->lchild); btree_cenorder(t->rchild); printf("%c\n",t->data); } //释放二叉树 int btree_destory(pBtree *B) { if(NULL == *B) return -1; btree_destory(&((*B)->lchild)); btree_destory(&((*B)->rchild)); free(*B); *B = NULL; return 0; }
main.c:
#include "btree.h" int main(int argc, char *argv[]) { pBtree t = btree_create(); //btree_create(&t); btree_preorder(t); printf("==========\n"); btree_cenorder(t); printf("==========\n"); btree_latorder(t); printf("==========\n"); /* 默认*号为NULL值,且为退出条件 * while(1){ printf("please input head->data:"); scanf("%c%*c",&(t->data)); if('*' == t->data) break; btree_create(&t); }; */ btree_destory(&t); if(NULL == t) fputs("this is NULL.\n",stdout); return 0; }
结果:
root@ubuntu:/mnt/U_share/DATA/tree/btree# make gcc ./src/*.c -o btree -I ./inc/ root@ubuntu:/mnt/U_share/DATA/tree/btree# ./btree A B C D E F G H ========== B D C A E H G F ========== B D C E H G F A ========== this is NULL.
总结:二叉树的遍历一般是看顺序,如果打印字符在遍历左子树前、遍历右子树后,便是先序,中序,后序类似,这里面用到了递归的思想,有递归创建二叉树,递归遍历二叉树,递归释放二叉树,也有普通一步步创建二叉树。
循环,goto语句
二叉树循环创建
perror
return
上述两者无意义,因为已经错了,而且还是处于递归创建中,①不清楚是那次malloc错误②既然创建失败,那么就算递归创建,也基本都会错误
释放不能先、中序,①释放根节点②释放左、根结点
先遍历,再释放
能插入、不过要约定插入规则,左孩子和右孩子为NULL的地方
遍历:先序、中序、后序、层次遍历
层次遍历不采用递归的方法(传左右孩子),深度
栈:先进后出
队列:先进先出⭐⭐⭐用队列来层次遍历、最好用链式队列⭐⭐⭐递归创建、层次遍历
=====================================================================
先序、中序求后序和中序、后序求先序的简单方法:
根据坐标画图便可先序:4 8 7 5 2 1 3 6 中序:5 7 2 8 4 3 1 6 后序:5 2 7 8 3 6 1 4 ①先序、中序求后序 4| 4 8| 8 7| 7 5| 5 2| 2 1| 1 3| 3 6| 6 ———————————————— 5 7 8 2 4 3 1 6 ②中序、后序求先序 5 7 8 2 4 3 1 6 ---------------- 4| 4 1| 1 6| 6 3| 3 8| 8 7| 7 2| 2 5| 5