二叉树大量用到递归思想
1.二叉树的概念
1.树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树(有且仅有一个根结点)。
2.二叉树的子节点分为左节点和右节点。 二叉树最多有两个子树(左右子树)
3.如果该二叉树的所有叶子节点都在最后一层,并且结点总数= 2^n -1 , n 为层数,则我们称为满二叉树。
4.如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。
二叉树的五种形态:
1、 空二叉树(什么都没有,nothing)
2、 只有一个根节点的二叉树(左右子树为空)
3、 右子树为空的二叉树(右腿断了)
4、 左子树为空的二叉树(左腿断了)
5、 左右子树都非空的的二叉树(既有左子树又有右子树,)
2.创建并遍历二叉树
先序遍历: 先访问父节点(根结点) -----> 先序遍历左子树 ------> 先序遍历右子树 (递归调用)
中序遍历: 先中序遍历左子树,再输出父节点,再中序遍历右子树
后序遍历: 先后遍历左子树,再后序遍历右子树,最后输出父节点
小结: 看输出父节点的顺序,就确定是前序,中序还是后序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 二叉树节点
struct BinTree_node
{
unsigned char elem;
struct BinTree_node *ltree, *rtree;
};
// 声明
struct BinTree_node *create_bintree(void);
void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree)
// 主函数
int main(void)
{
struct BinTree_node *mytree;
mytree = create_bintree();
// pre_order(mytree);
// in_order(mytree);
pos_order(mytree);
printf("\n");
return 0;
}
// 创建树
struct BinTree_node *create_bintree(void)
{
unsigned char flag;
struct BinTree_node *tree;
tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
printf("please input the mode elem:\n");
while((tree->elem = getchar()) == '\n');
//左子树
printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
while((flag = getchar()) == '\n'); //避免连续getchar(),该方法避免回车
if(flag == 'Y')
tree->ltree = create_bintree(); //递归创建左子树
else
tree->ltree = NULL;
//右子树
printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
while((flag = getchar()) == '\n'); //避免连续getc har(),该方法避免回车
if(flag == 'Y')
tree->rtree = create_bintree(); //递归创建左子树
else
tree->rtree = NULL;
return tree;
}
// 先序遍历函数 ABDECFG
void pre_order(struct BinTree_node *tree)
{
if(tree)
{
printf("%c", tree->elem);
pre_order(tree->ltree);
pre_order(tree->rtree);
}
}
// 中序遍历函数 DBEAFGC
void in_order(struct BinTree_node *tree)
{
if(tree)
{
in_order(tree->ltree);
printf("%c", tree->elem);
in_order(tree->rtree);
}
}
// 后序遍历函数 DEBGFCA
void pos_order(struct BinTree_node *tree)
{
if(tree)
{
pos_order(tree->ltree);
pos_order(tree->rtree);
printf("%c", tree->elem);
}
}
3.遍历二叉树(层次遍历)
层次遍历即为从上到下,从左到右依次访问二叉树的每个结点。
实现思路
(1)我们定义一个队列,先将根结点入队;
(2)当前结点是队头结点,将其出队并访问;
(3)若当前结点的左结点不为空将左结点入队;若当前结点的右结点不为空将其入队即可。
只要队列不为空
{
队列头出队列
打印节点数据域
如果有左子树
左子树节点入队列
如果有右子树
右子树节点入队列 --------》再次循环
}
例图
queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <stdio.h>
#include "binary_tree.h" //包含二叉树
# define SIZE 512 // 宏定义
//函数声明
int is_empty(void);
int is_full(void);
void enqueue(struct BinTree_node c);
struct BinTree_node dequeue(void);
#endif
queue.c
# include "queue.h"
struct BinTree_node queue[SIZE];
int head = 0, tail = 0;
//循环队列入队
void enqueue(struct BinTree_node c)
{
queue[tail] = c;
tail = (tail+1) % SIZE;
}
//出队
struct BinTree_node dequeue(void)
{
struct BinTree_node ch;
ch = queue[head];
head = (head + 1) % SIZE;
return ch;
}
//判断队列是否为空
int is_empty(void)
{
return head == tail;
}
//判断队列为满
int is_full(void)
{
return (tail + 1) % SIZE == head;
}
binary_tree.h
#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__
#include <stdio.h>
#include <stdlib.h>
// enqueue(struct BinTree_node c);
// 二叉树节点
struct BinTree_node
{
unsigned char elem;
struct BinTree_node *ltree, *rtree;
};
#include "queue.h"
// 声明
struct BinTree_node *create_bintree(void);
void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree);
void level_traverse(struct BinTree_node *tree);
#endif
binary_tree.c
#include "binary_tree.h"
// 创建树
struct BinTree_node *create_bintree(void)
{
unsigned char flag;
struct BinTree_node *tree;
tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
printf("please input the mode elem:\n");
while((tree->elem = getchar()) == '\n');
//左子树
printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
while((flag = getchar()) == '\n'); //避免连续getchar(),该方法避免回车
if(flag == 'Y')
tree->ltree = create_bintree(); //递归创建左子树
else
tree->ltree = NULL;
//右子树
printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
while((flag = getchar()) == '\n'); //避免连续getc har(),该方法避免回车
if(flag == 'Y')
tree->rtree = create_bintree(); //递归创建左子树
else
tree->rtree = NULL;
return tree;
}
// 先序遍历函数 ABDECFG
void pre_order(struct BinTree_node *tree)
{
if(tree)
{
printf("%c", tree->elem);
pre_order(tree->ltree);
pre_order(tree->rtree);
}
}
// 中序遍历函数 DBEAFGC
void in_order(struct BinTree_node *tree)
{
if(tree)
{
in_order(tree->ltree);
printf("%c", tree->elem);
in_order(tree->rtree);
}
}
// 后序遍历函数 DEBGFCA
void pos_order(struct BinTree_node *tree)
{
if(tree)
{
pos_order(tree->ltree);
pos_order(tree->rtree);
printf("%c", tree->elem);
}
}
void level_traverse(struct BinTree_node *tree)
{
struct BinTree_node node; //接收出队的队列头
enqueue(*tree);
while(!is_empty())
{
node = dequeue();
printf("%c", node.elem);
if(node.ltree)
{
enqueue(*node.ltree);
}
if(node.rtree)
{
enqueue(*node.rtree);
}
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "binary_tree.h"
// 主函数
int main(void)
{
struct BinTree_node *mytree;
mytree = create_bintree();
//层次遍历
level_traverse(mytree);
printf("\n");
return 0;
}
//输出 ABCDEFG
4.统计二叉树的深度,叶子数,节点数
二叉树的深度:层数
(1) 二叉树为空 -------->深度为0
(2) 一般二叉树深度 = 左右字树最大深度 + 1
二叉树的叶子数:最低节点数
(1) 二叉树为空 -------->叶子数为0
(2) 二叉树只有根结点 ,没有左右子树 --------> 叶子数 1
(3) 一般情况下,左子树叶子数 + 右子树叶子数
二叉树节点个数:
(1) 二叉树为空 -------->节点数为0
(2) 一般情况下,左子树节点数 + 右子树节点数
queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <stdio.h>
#include "binary_tree.h" //包含二叉树
# define SIZE 512 // 宏定义
//函数声明
int is_empty(void);
int is_full(void);
void enqueue(struct BinTree_node c);
struct BinTree_node dequeue(void);
#endif
queue.c
# include "queue.h"
struct BinTree_node queue[SIZE];
int head = 0, tail = 0;
//循环队列入队
void enqueue(struct BinTree_node c)
{
queue[tail] = c;
tail = (tail+1) % SIZE;
}
//出队
struct BinTree_node dequeue(void)
{
struct BinTree_node ch;
ch = queue[head];
head = (head + 1) % SIZE;
return ch;
}
//判断队列是否为空
int is_empty(void)
{
return head == tail;
}
//判断队列为满
int is_full(void)
{
return (tail + 1) % SIZE == head;
}
binary_tree.h
#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__
#include <stdio.h>
#include <stdlib.h>
// enqueue(struct BinTree_node c);
// 二叉树节点
struct BinTree_node
{
unsigned char elem;
struct BinTree_node *ltree, *rtree;
};
#include "queue.h"
// 声明
struct BinTree_node *create_bintree(void);
void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree);
void level_traverse(struct BinTree_node *tree);
unsigned int depth(struct BinTree_node *tree);
unsigned int leaf_num(struct BinTree_node *tree);
unsigned int node_num(struct BinTree_node *tree);
#endif
binary_tree.c
#include "binary_tree.h"
// 创建树
struct BinTree_node *create_bintree(void)
{
unsigned char flag;
struct BinTree_node *tree;
tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
printf("please input the mode elem:\n");
while((tree->elem = getchar()) == '\n');
//左子树
printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
while((flag = getchar()) == '\n'); //避免连续getchar(),该方法避免回车
if(flag == 'Y')
tree->ltree = create_bintree(); //递归创建左子树
else
tree->ltree = NULL;
//右子树
printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
while((flag = getchar()) == '\n'); //避免连续getc har(),该方法避免回车
if(flag == 'Y')
tree->rtree = create_bintree(); //递归创建左子树
else
tree->rtree = NULL;
return tree;
}
// 先序遍历函数 ABDECFG
void pre_order(struct BinTree_node *tree)
{
if(tree)
{
printf("%c", tree->elem);
pre_order(tree->ltree);
pre_order(tree->rtree);
}
}
// 中序遍历函数 DBEAFGC
void in_order(struct BinTree_node *tree)
{
if(tree)
{
in_order(tree->ltree);
printf("%c", tree->elem);
in_order(tree->rtree);
}
}
// 后序遍历函数 DEBGFCA
void pos_order(struct BinTree_node *tree)
{
if(tree)
{
pos_order(tree->ltree);
pos_order(tree->rtree);
printf("%c", tree->elem);
}
}
void level_traverse(struct BinTree_node *tree)
{
struct BinTree_node node; //接收出队的队列头
enqueue(*tree);
while(!is_empty())
{
node = dequeue();
printf("%c", node.elem);
if(node.ltree)
{
enqueue(*node.ltree);
}
if(node.rtree)
{
enqueue(*node.rtree);
}
}
}
//计算二叉树深度
unsigned int depth(struct BinTree_node *tree)
{
unsigned int l_depth;
unsigned int r_depth;
if(tree == NULL)
return 0;
else
{
l_depth = depth(tree->ltree);
r_depth = depth(tree->rtree);
return (l_depth > r_depth) ? (l_depth + 1) : (r_depth + 1);
}
}
//计算二叉树叶子数
unsigned int leaf_num(struct BinTree_node *tree)
{
if(tree == NULL)
return 0;
else if((tree->ltree ==NULL) && (tree->rtree ==NULL))
return 1;
else
return leaf_num(tree->ltree) + leaf_num(tree->rtree);
}
//计算二叉树节点数
unsigned int node_num(struct BinTree_node *tree)
{
if(tree == NULL)
return 0;
else
return node_num(tree->ltree) + node_num(tree->ltree) + 1;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "binary_tree.h"
// 主函数
int main(void)
{
struct BinTree_node *mytree;
mytree = create_bintree();
//层次遍历
level_traverse(mytree);
printf("\n");
printf("depth = %d\n", depth(mytree)); // 二叉树深度
printf("leaf_num = %d\n", leaf_num(mytree)); // 叶子数
printf("\n");
printf("node_num = %d\n", node_num(mytree)); // 叶子数
printf("\n");
return 0;
}