树是一种非线性的数据结构,树有根节点,子树等概念。
二叉树(Binary Tree):每个节点最多有两颗子树,并且子树有左右之分。
概念:树的深度,满二叉树,完全二叉树,树的节点树
二叉树包括顺序存储和链式存储,这里只说链式存储。二叉树的每个节点和双链表有些类似,但是树的结构要比双链表复杂,在构造树的过程中涉及到递归调用的问题,递归的问题往往是很复杂的问题,因此,这里单独说二叉树的构建。
国际惯例,先上代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<malloc.h> 4 5 //定义二叉树 6 typedef struct node{ 7 int data;//数据元素 8 struct node *left;//指向左子树 9 struct node *right;//指向右子树 10 }BTree; 11 12 //构造二叉树 13 int BTreeCreate(BTree **tp) 14 { 15 //构造方法,或者说构造顺序:从左子树开始构造 16 int x; 17 scanf("%d",&x); 18 if(x<0) 19 { 20 *tp=NULL;//指针为空,树节点中的某个指针为空 21 return 0; 22 } 23 *tp=(BTree*)malloc(sizeof(BTree));//将树节点中指针指向该地址空间 24 if(tp==NULL) 25 return 0; 26 (*tp)->data=x; 27 BTreeCreate(&((*tp)->left)); 28 BTreeCreate(&((*tp)->right)); 29 return 1; 30 } 31 32 int main() 33 { 34 BTree *tree; 35 printf("Create binary tree:\n"); 36 BTreeCreate(&tree); 37 38 return 0; 39 }
代码看似比较简单,核心就是BTreeCreate函数,该函数完成二叉树的构建,根据函数定义,只有输入正整数时才会新建节点。
二叉树的构建过程如下:
先创建某一子树的左子树,如果左子树不存在(输入负数时),则创建其右子树,如果左子树存在,再创建该树的左子树,依次循环。需要注意的是,当某一子树左子树不存在则判断其右子树,右子树不存在则返回其父节点再判断右子树。
特别要注意的是,一旦一个节点创建成功,则它的左子树和右子树都要判断,不论它们存不存在,因为此BTreeCreate调用,输入正整数,即节点创建成功后,都会去创建的left和right。
示例:就上面的程序,在第38行设置断点,依次输入1,2,-1,3,-1,-2,-3,tree指针的存储结构如下(也就是树的存储结构)
根据输入的数据,可以划出如下树的结构图:
对比上面的内存存储情况,可以看得很明白,蓝色的圈圈就是真正的树节点。树的构建过程如下:
输入1,创建主节点,接下来创建1的左子树,创建1右子树的函数等待,设函数入口地址为ad1
输入2,主节点1的左子树创建成功,接下来创建2的左子树,创建2右子树的函数等待,设函数入口地址为ad2
输入-1,节点2的左子树创建失败,返回执行等待的的函数(离当前最近的),即ad2,创建节点2的右子树
输入3,节点2的右子树创建成功,接下来创建节点3的左子树,创建3右子树的函数等待,函数入口地址ad2
。。。。。。
直到函数递归调用完毕,没有等待的函数为止。
下面创建一个完全二叉树验证结果,树的结构图下:
输入:1,2,4,-1,-2,5,-3,-4,3,-5,-6,树的内存存储如下: