由一个或多个(n≥0)结点组成的有限集合T ,
有且仅有一个结点称为根( root ) ,
当n>1时,
其余的结点分为m(m≥0)个互不相交的有限集合T1,T2,…,Tm。
每个集合本身又是棵树,被称作这个根的子树。
( 1:n )
根
→即根结点(没有前驱)叶子
→即终端结点(没有后继)双亲
→即上层的那个结点(直接前驱) parent孩子
→即下层结点的子树(直接后继)child-上图中的结点数 = 13 ,树的度 = 3 ,数的深度 = 4
事物之问的逻辑关系可以通过数的形式很直观的表示出来,如下图:
用广义表表示法表示上图:
中国(河北(保定,石家庄),广东(广州,东莞),山东(青岛,济南))
根作为由子树森林组成的表的名宁写在表的左边。
左孩子右兄弟表示法可以将一颗多叉树转化为一颖二叉树:
n ( n≥0 )个结点的有限集合,由一个根结点以及两棵互不相交的、分别称为左子树和
右子树的二叉树组成。
一对二(1:2)
每个结点最多只有两棵子树(丕存在度大于2的结点);
左子树和右子树次序不能颠倒(有序树)
特点:每层都有”充满”了结点
除最后一层外,每一层上的节点均达到最大值;在最后一层上只缺少右边的若干结点
理解:k-1层与满二叉树完全相同,第k层结点尽量靠左
指按某条搜索路线遍访每个结点且不重复(又称周游入
它是树结构插入、删除、修改、查找和排序运算的前提,是二叉树一切运算的基础和核
心。
牢记一种约定,对每个结点的查看都是“先左后右”。
限定先左后右,树的遍历有三种实现方案∶
注:"先、中、后”的意思是指访问的结点D是先于子树出现还是后于子树出现。
从递归的角度看,这三种算法是完全相同的,
或者说这三种遍历算法的访问路径是相同的,
只是访问结点的时机不同。
从虚线的出发点到终点的路径上,每个结点经过3次。
先序遍历:根 左 右
中序遍历:左 根 右
后续遍历:左 右 根
#include <stdio.h> #include "string.h" #include "stdlib.h" struct BinaryNode{ char ch;//数据域 struct BinaryNode * LChild;//左孩子节点 struct BinaryNode * RChild;//右孩子节点 }; //递归遍历的函数 void recursion(struct BinaryNode * root){ if(root == NULL){ return; } //先序遍历,先根 再左 再右 printf ("%c ",root->ch); recursion (root->LChild); recursion (root->RChild); } void test01(){ struct BinaryNode nodeA = {'A',NULL,NULL}; struct BinaryNode nodeB = {'B',NULL,NULL}; struct BinaryNode nodeC = {'C',NULL,NULL}; struct BinaryNode nodeD = {'D',NULL,NULL}; struct BinaryNode nodeE = {'E',NULL,NULL}; struct BinaryNode nodeF = {'F',NULL,NULL}; struct BinaryNode nodeG = {'G',NULL,NULL}; struct BinaryNode nodeH = {'H',NULL,NULL}; //建立结点之间的关系 nodeA.LChild = &nodeB; nodeA.RChild = &nodeF; nodeB.RChild = &nodeC; nodeC.LChild = &nodeD; nodeC.RChild = &nodeE; nodeF.RChild = &nodeG; nodeG.LChild = &nodeH; //递归遍历 recursion(&nodeA); } int main () { test01(); return 0; }
运行结果
#include <stdio.h> #include "string.h" #include "stdlib.h" struct BinaryNode{ char ch;//数据域 struct BinaryNode * LChild;//左孩子节点 struct BinaryNode * RChild;//右孩子节点 }; //递归遍历的函数 void preorderRecursion(struct BinaryNode * root){ if(root == NULL){ return; } //先序遍历,先根 再左 再右 printf ("%c ",root->ch); preorderRecursion (root->LChild); preorderRecursion (root->RChild); } //递归遍历的函数 void inRecursion(struct BinaryNode * root){ if(root == NULL){ return; } //中序遍历,先根 再左 再右 inRecursion (root->LChild); printf ("%c ",root->ch); inRecursion (root->RChild); } //递归遍历的函数 void afterRecursion(struct BinaryNode * root){ if(root == NULL){ return; } //中序遍历,先根 再左 再右 afterRecursion (root->LChild); afterRecursion (root->RChild); printf ("%c ",root->ch); } void test01(){ struct BinaryNode nodeA = {'A',NULL,NULL}; struct BinaryNode nodeB = {'B',NULL,NULL}; struct BinaryNode nodeC = {'C',NULL,NULL}; struct BinaryNode nodeD = {'D',NULL,NULL}; struct BinaryNode nodeE = {'E',NULL,NULL}; struct BinaryNode nodeF = {'F',NULL,NULL}; struct BinaryNode nodeG = {'G',NULL,NULL}; struct BinaryNode nodeH = {'H',NULL,NULL}; //建立结点之间的关系 nodeA.LChild = &nodeB; nodeA.RChild = &nodeF; nodeB.RChild = &nodeC; nodeC.LChild = &nodeD; nodeC.RChild = &nodeE; nodeF.RChild = &nodeG; nodeG.LChild = &nodeH; //递归遍历 printf("先序遍历\n"); preorderRecursion(&nodeA); printf("\n中序遍历\n"); inRecursion(&nodeA); printf("\n后序遍历\n"); afterRecursion(&nodeA); } int main () { test01(); return 0; }
运行结果
#include <stdio.h> #include "string.h" #include "stdlib.h" struct BinaryNode{ char ch;//数据域 struct BinaryNode * LChild;//左孩子节点 struct BinaryNode * RChild;//右孩子节点 }; //统计叶子数量的函数 void calculateLeafNum(struct BinaryNode * root, int * num){ //递归的结束条件 if(root == NULL){ return; } //判断当前节点的左孩子和右孩子是否为空。如果为空数字就累加 if(root->LChild == NULL && root->RChild == NULL){ (*num)++; } calculateLeafNum (root->LChild,num); calculateLeafNum (root->RChild,num); } void test01(){ struct BinaryNode nodeA = {'A',NULL,NULL}; struct BinaryNode nodeB = {'B',NULL,NULL}; struct BinaryNode nodeC = {'C',NULL,NULL}; struct BinaryNode nodeD = {'D',NULL,NULL}; struct BinaryNode nodeE = {'E',NULL,NULL}; struct BinaryNode nodeF = {'F',NULL,NULL}; struct BinaryNode nodeG = {'G',NULL,NULL}; struct BinaryNode nodeH = {'H',NULL,NULL}; //建立结点之间的关系 nodeA.LChild = &nodeB; nodeA.RChild = &nodeF; nodeB.RChild = &nodeC; nodeC.LChild = &nodeD; nodeC.RChild = &nodeE; nodeF.RChild = &nodeG; nodeG.LChild = &nodeH; //求树中的叶子的数量 int num = 0; calculateLeafNum(&nodeA ,&num); printf ("LeafNum=%d",num); } int main () { test01(); return 0; }
int getTreeHeight(struct BinaryNode* root){ if(root == NULL){ return 0; } //求出左子树的高度 int LHeight = getTreeHeight(root->LChild); //计算右子树的高度 int RHeight = getTreeHeight(root->RChild); //取左子树和右子树,中最大的值 +1 int height = LHeight > RHeight ? LHeight + 1 : RHeight + 1; return height; }
计算相关的所有代码
#include <stdio.h> struct BinaryNode{ char ch;//数据域 struct BinaryNode * LChild;//左孩子节点 struct BinaryNode * RChild;//右孩子节点 }; //统计叶子数量的函数 void calculateLeafNum(struct BinaryNode * root, int * num){ //递归的结束条件 if(root == NULL){ return; } //判断当前节点的左孩子和右孩子是否为空。如果为空数字就累加 if(root->LChild == NULL && root->RChild == NULL){ (*num)++; } calculateLeafNum (root->LChild,num); calculateLeafNum (root->RChild,num); } int getTreeHeight(struct BinaryNode* root){ if(root == NULL){ return 0; } //求出左子树的高度 int LHeight = getTreeHeight(root->LChild); //计算右子树的高度 int RHeight = getTreeHeight(root->RChild); //取左子树和右子树,中最大的值 +1 int height = LHeight > RHeight ? LHeight + 1 : RHeight + 1; return height; } void test01(){ struct BinaryNode nodeA = {'A',NULL,NULL}; struct BinaryNode nodeB = {'B',NULL,NULL}; struct BinaryNode nodeC = {'C',NULL,NULL}; struct BinaryNode nodeD = {'D',NULL,NULL}; struct BinaryNode nodeE = {'E',NULL,NULL}; struct BinaryNode nodeF = {'F',NULL,NULL}; struct BinaryNode nodeG = {'G',NULL,NULL}; struct BinaryNode nodeH = {'H',NULL,NULL}; //建立结点之间的关系 nodeA.LChild = &nodeB; nodeA.RChild = &nodeF; nodeB.RChild = &nodeC; nodeC.LChild = &nodeD; nodeC.RChild = &nodeE; nodeF.RChild = &nodeG; nodeG.LChild = &nodeH; //1、求树中的叶子的数量 int num = 0; calculateLeafNum(&nodeA ,&num); printf ("LeafNum=%d\n",num); //2、求树的高度、深度 int height = getTreeHeight(&nodeA); printf ("tree height is=%d\n",height); } int main () { test01(); return 0; }
struct BinaryNode * copyBinaryTree(struct BinaryNode* root){ if(root == NULL){ return NULL; } //先拷贝 左子树 struct BinaryNode * LChild = copyBinaryTree (root->LChild); //再拷贝 右子树 struct BinaryNode * RChild = copyBinaryTree (root->RChild); //创建新的节点 struct BinaryNode * newNode = malloc(sizeof (struct BinaryNode )); newNode->LChild = LChild; newNode->RChild = RChild; //返回给新用户 newNode->ch = root->ch; return newNode; }
//遍历树 void showBinaryTree(struct BinaryNode * root){ if(root == NULL){ return; } printf ("%c",root->ch); showBinaryTree (root->LChild); showBinaryTree (root->RChild); }
全部测试代码
#include <stdio.h> #include "string.h" #include "stdlib.h" struct BinaryNode{ char ch;//数据域 struct BinaryNode * LChild;//左孩子节点 struct BinaryNode * RChild;//右孩子节点 }; //统计叶子数量的函数 void calculateLeafNum(struct BinaryNode * root, int * num){ //递归的结束条件 if(root == NULL){ return; } //判断当前节点的左孩子和右孩子是否为空。如果为空数字就累加 if(root->LChild == NULL && root->RChild == NULL){ (*num)++; } calculateLeafNum (root->LChild,num); calculateLeafNum (root->RChild,num); } int getTreeHeight(struct BinaryNode* root){ if(root == NULL){ return 0; } //求出左子树的高度 int LHeight = getTreeHeight(root->LChild); //计算右子树的高度 int RHeight = getTreeHeight(root->RChild); //取左子树和右子树,中最大的值 +1 int height = LHeight > RHeight ? LHeight + 1 : RHeight + 1; return height; } struct BinaryNode * copyBinaryTree(struct BinaryNode* root){ if(root == NULL){ return NULL; } //先拷贝 左子树 struct BinaryNode * LChild = copyBinaryTree (root->LChild); //再拷贝 右子树 struct BinaryNode * RChild = copyBinaryTree (root->RChild); //创建新的节点 struct BinaryNode * newNode = malloc(sizeof (struct BinaryNode )); newNode->LChild = LChild; newNode->RChild = RChild; //返回给新用户 newNode->ch = root->ch; return newNode; } //遍历树 void showBinaryTree(struct BinaryNode * root){ if(root == NULL){ return; } printf ("%c",root->ch); showBinaryTree (root->LChild); showBinaryTree (root->RChild); } void test01(){ struct BinaryNode nodeA = {'A',NULL,NULL}; struct BinaryNode nodeB = {'B',NULL,NULL}; struct BinaryNode nodeC = {'C',NULL,NULL}; struct BinaryNode nodeD = {'D',NULL,NULL}; struct BinaryNode nodeE = {'E',NULL,NULL}; struct BinaryNode nodeF = {'F',NULL,NULL}; struct BinaryNode nodeG = {'G',NULL,NULL}; struct BinaryNode nodeH = {'H',NULL,NULL}; //建立结点之间的关系 nodeA.LChild = &nodeB; nodeA.RChild = &nodeF; nodeB.RChild = &nodeC; nodeC.LChild = &nodeD; nodeC.RChild = &nodeE; nodeF.RChild = &nodeG; nodeG.LChild = &nodeH; printf ("show BinaryTree\n"); showBinaryTree(&nodeA); //1、求树中的叶子的数量 int num = 0; calculateLeafNum(&nodeA ,&num); printf ("\nLeafNum=%d\n",num); //2、求树的高度、深度 int height = getTreeHeight(&nodeA); printf ("tree height is=%d\n",height); //3、拷贝二叉树 struct BinaryNode * newTree = copyBinaryTree(&nodeA); printf ("show Copy BinaryTree\n"); showBinaryTree(newTree); } int main () { test01(); return 0; }
运行结果
//释放二叉树freeTree void freeTree(struct BinaryNode * root ) { if(root == NULL){ return; } //先释放左子树 freeTree (root->LChild); //再释放右子树 freeTree (root->RChild); printf ("%c __is free\n",root->ch); //释放根节点 free(root); }
运行测试所有代码
#include <stdio.h> #include "string.h" #include "stdlib.h" struct BinaryNode{ char ch;//数据域 struct BinaryNode * LChild;//左孩子节点 struct BinaryNode * RChild;//右孩子节点 }; //统计叶子数量的函数 void calculateLeafNum(struct BinaryNode * root, int * num){ //递归的结束条件 if(root == NULL){ return; } //判断当前节点的左孩子和右孩子是否为空。如果为空数字就累加 if(root->LChild == NULL && root->RChild == NULL){ (*num)++; } calculateLeafNum (root->LChild,num); calculateLeafNum (root->RChild,num); } int getTreeHeight(struct BinaryNode* root){ if(root == NULL){ return 0; } //求出左子树的高度 int LHeight = getTreeHeight(root->LChild); //计算右子树的高度 int RHeight = getTreeHeight(root->RChild); //取左子树和右子树,中最大的值 +1 int height = LHeight > RHeight ? LHeight + 1 : RHeight + 1; return height; } struct BinaryNode * copyBinaryTree(struct BinaryNode* root){ if(root == NULL){ return NULL; } //先拷贝 左子树 struct BinaryNode * LChild = copyBinaryTree (root->LChild); //再拷贝 右子树 struct BinaryNode * RChild = copyBinaryTree (root->RChild); //创建新的节点 struct BinaryNode * newNode = malloc(sizeof (struct BinaryNode )); newNode->LChild = LChild; newNode->RChild = RChild; //返回给新用户 newNode->ch = root->ch; return newNode; } //遍历树 void showBinaryTree(struct BinaryNode * root){ if(root == NULL){ return; } printf ("%c",root->ch); showBinaryTree (root->LChild); showBinaryTree (root->RChild); } //释放二叉树freeTree void freeTree(struct BinaryNode * root ) { if(root == NULL){ return; } //先释放左子树 freeTree (root->LChild); //再释放右子树 freeTree (root->RChild); printf ("%c __is free\n",root->ch); //释放根节点 free(root); } void test01(){ struct BinaryNode nodeA = {'A',NULL,NULL}; struct BinaryNode nodeB = {'B',NULL,NULL}; struct BinaryNode nodeC = {'C',NULL,NULL}; struct BinaryNode nodeD = {'D',NULL,NULL}; struct BinaryNode nodeE = {'E',NULL,NULL}; struct BinaryNode nodeF = {'F',NULL,NULL}; struct BinaryNode nodeG = {'G',NULL,NULL}; struct BinaryNode nodeH = {'H',NULL,NULL}; //建立结点之间的关系 nodeA.LChild = &nodeB; nodeA.RChild = &nodeF; nodeB.RChild = &nodeC; nodeC.LChild = &nodeD; nodeC.RChild = &nodeE; nodeF.RChild = &nodeG; nodeG.LChild = &nodeH; printf ("show BinaryTree\n"); showBinaryTree(&nodeA); //1、求树中的叶子的数量 int num = 0; calculateLeafNum(&nodeA ,&num); printf ("\nLeafNum=%d\n",num); //2、求树的高度、深度 int height = getTreeHeight(&nodeA); printf ("tree height is=%d\n",height); //3、拷贝二叉树 struct BinaryNode * newTree = copyBinaryTree(&nodeA); printf ("show Copy BinaryTree\n"); showBinaryTree(newTree); //4、释放二叉树 freeTree(newTree); } int main () { test01(); return 0; }