1.定义:树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。
- 节点的度:一个节点含有的子树的个数称为该节点的度;
- 树的度:一棵树中,最大的节点的度称为树的度;
-
节点的层次:节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
-
树的深度:树中节点的最大层次 ;
-
叶节点:度为0的节点。
-
二叉树:是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。
-
二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
-
2.满二叉树:除在二叉树最下层的节点外,每层的节点都有两个子节点。
3.完全二叉树:除最后一层外,其他各层的节点数都达到最大个数,且最后一层节点是从左到右的连续存在。满二叉树是一种特殊的完全二叉树。
-
有n个节点的完全二叉树,若从上往下,从左到右,从0开始给节点编号,那么:
-
parent = (child-1)/2;
-
leftchild = parent*2 + 1; 若结果大于n,则无左孩子。
-
rightchild = parent*2 + 2; 若结果大于n,则无右孩子。
-
4.树的存储方式:
-
顺序存储:顺序结构存储就是使用数组来存储,如果节点为空,要把空间留出来。会造成空间浪费,适合存储满二叉树和完全二叉树。
-
链式存储:二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。链式存储结构的结点包含三个部分,分别是数据域、左指针域、右指针域。
5.C语言二叉树的链式存储的实现:
1.二叉树的创建以及销毁
typedef int BTDataType;
typedef struct BinaryTreeNode{
BTDataType data;//数据
struct BinaryTreeNode *lNode;//左子节点
struct BinaryTreeNode *rNode;//右子节点
}BTNode;
//创建一个节点
BTNode * NodeCreate(BTDataType data){
BTNode * node = (BTNode *) malloc(sizeof(BTNode));
if(node == NULL){
printf("malloc failed\n");
exit(-1);
}
node->data = data;
node->lNode = NULL;
node->rNode = NULL;
return node;
}
//二叉树的销毁
void BTDestory(BTNode * root){
if(root==NULL){
return;
}
BTDestory(root->lNode);
BTDestory(root->rNode);
free(root);
}
2.二叉树的遍历
//前序遍历:输出顺序:根节点、左子树、右子树;
//中序遍历:输出顺序:左子树、根节点、右子树,将打印函数往后放一句;
//后序遍历:输出顺序:左子树、右子树、根节点,将打印函数往后放两句;
void prevOrder(BTNode * root){ //前序遍历
if(root==NULL){
return;
}
printf("%d\n",root->data);
prevOrder(root->lNode);
prevOrder(root->rNode);
}
//层序遍历:需要用到队列相关知识,具体参考队列一章
void levelOrder(BTNode * root){
if(root==NULL){
return;
}
Queue *queue = QueueCreate();
QueuePush(queue,root);
while( !IsEmpty(queue) ){
BTNode *cur = QueueFront(queue);
QueuePop(queue);
printf("%d\n",cur->data);
if(cur->lNode != NULL){
QueuePush(queue,cur->lNode);
}
if(cur->rNode != NULL){
QueuePush(queue,cur->rNode);
}
}
QueueDestory(queue);
}
3.二叉树非空节点个数
//1.如果是空树,则返回0
//2.不是空,节点个数=左子树节点个数+右子树节点个数+1(自己)
int BTSize(BTNode *root){
return root==NULL ? (0) : BTSize(root->lNode)+ BTSize(root->rNode) + 1;
}
4.二叉树叶子节点个数
//1.如果是空树,则返回0
//2.如果根节点的左右子节点都是空则返回1
//3.否则=左子树的叶子结点个数+右子树的叶子节点个数
int BTLeafSize(BTNode *root){
if(root==NULL){
return 0;
}
if(root->rNode == NULL && root->lNode ==NULL){
return 1;
}
return BTLeafSize(root->lNode) + BTLeafSize(root->rNode);
}
5.二叉树第k层节点个数
//1.空树,返回0
//2.k=1,返回1
//3.k>1;等于左子节点k-1层节点个数 + 右子节点k-1层节点个数
int BTlevelSize(BTNode * root, int k){
if(root==NULL){
return 0;
}
if(k==1){
return 1;
}
return BTlevelSize(root->lNode,k-1) + BTlevelSize(root->rNode,k-1);
}
6.查找第一个值为k的节点
//1.空树,返回空
//2.判断根节点是不是
//3.在左子节点中寻找,如果没有,再去右子节点寻找,都没有返回空
BTNode * BTFind(BTNode *root,BTDataType k){
if(root == NULL){
return NULL;
}
if(root->data == k){
return root;
}
BTNode *lRes = BTFind(root->lNode,k);
if(lRes != NULL){
return lRes;
}
BTNode *rRes = BTFind(root->rNode,k);
if(rRes != NULL){
return rRes;
}
return NULL;
}
7.二叉树的深度
//1.空树,返回0
//2.非空=左右子树深度最大的 + 1
int BTDepth(BTNode * root){
if(root==NULL){
return 0;
}
int r = BTDepth(root->rNode);
int l = BTDepth(root->lNode);
return r > l ? (r+1) : (l+1);
}