文章目录
二叉树初步学习
本篇为二叉树初步学习内容。
一.二叉树的种类
二叉树一般被分为两种,满二叉树
以及完全二叉树
。
1.满二叉树
指的是:除了最后一层无任何子节点,其余每一层的节点都有两个子节点的二叉树。
国内教程定义:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
如图所示:
深度为k。
2.完全二叉树
指的是除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。
这个是完全二叉树。
这个不是完全二叉树。
若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。
3.二叉搜索树
二叉搜索树是有数值的树,是一个有序树。
- 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
每一个左、右子树也分别为二叉排序树。
4.平衡二叉搜索树
又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
这不是平衡二叉树,因为其左右两个子树高度绝对值相差超过1。
二.二叉树的存储方式
二叉树的存储分为两种:链式存储和顺序存储。
链式存储
顺序存储指的是用数组存储,链式存储则用指针存储。
链式存储如图所示:
链式存储和我们学过的链表非常像,那么顺序存储呢?
顺序存储
顺序存储则是和数组一样,如图所示:
那么用数组来存储二叉树该如何遍历?
顺序数组的遍历:
若果父节点的数组下标为i,那么它的左孩子就是2 * i+1,右孩子就是2 * i+2。
相比于用数组去表示二叉树,用链表更容易我们理解。
三.二叉树的创建
要实现二叉树的链式存储,我们需要在结构体定义环节对每个节点的左孩子节点和右孩子节点的地址进行保存。
结构体表示如下:
typedef struct tree
{
char data;//存放本节点数据
struct tree* left;//存放左孩子节点地址
struct tree* right;//存放右孩子节点地址
}Tree;
接下来我们可以创建二叉树:
Tree *Create_Tree()
{
Tree *root;
char ch;
scanf("%c", &ch);//通过输入的ch是否为特殊符号来判断该节点是否有孩子节点
if(ch == '#'){ //不存在孩子节点
return NULL;
}
else{
root = (Tree *)malloc(sizeof(Tree));
if(NULL == root){
printf("创建失败\n");
return NULL;
}
root->data = ch;
root->left = Create_Tree();//存在左孩子节点,递归调用本函数,使得左孩子节点先被赋值
root->right = Create_Tree();
return root;
}
}
创建二叉树主要用了递归的方式,靠左创建。
先执行root->left = Create_Tree(),向左到最后一层,然后归一层,再执行root->right = Create_Tree(),这样就可以完成二叉树的创建。
四.树的遍历
树的遍历分为四种:先序遍历,中序遍历,后续遍历,层次遍历。
1.先序遍历
遍历顺序为:根节点->左孩子树->右孩子树
void Preorder_Tree(Tree *root)
{
if(NULL == root){
return;
}
printf("%c ", root->data);//输出当前节点的数据
Preorder_Tree(root->l_child);//将子节点作为下一个根节点遍历左孩子数
Preorder_Tree(root->r_child);//将子节点作为下一个根节点遍历左孩子数
}
先会输出根节点的内容,然后向左遍历,边遍历边输出,遇到NULL后归,再输出右边的内容。
输出结果为:ABCDEFGHK
2.中序遍历
遍历顺序为:左孩子树->根节点->右孩子树
void Mediate_Tree(Tree *root)
{
if(NULL == root){
return;
}
Mediate_Tree(root->l_child);
printf("%c ", root->data);
Mediate_Tree(root->r_child);
}
先向左遍历到最左边的节点,输出后回退,再输出根节点,最后输出右节点。
输出结果为:BDCAEHGKF
3.后序遍历
遍历顺序为:左孩子树->右孩子树->根节点
void Post_Tree(Tree *root)
{
if(NULL == root){
return;
}
Post_Tree(root->l_child);
Post_Tree(root->r_child);
printf("%c ", root->data);
}
输出顺序为从左到右,从下到上,最后输出最开始的根节点。
输出结果为:DCBHKGFEA
4.层次遍历
该部分运用了队列的相关知识,本人还正在学,所以只展示代码
void Level_Tree(Tree *tree)
{
if(tree == NULL){
return;
}
Tree *pos[N];
int front, rear;//对头指针和对尾指针,用于出队和入队操作
rear = N;
while(rear--){
pos[rear] = NULL;//全部置为空,方便后续判断
}
front = rear = 1;//此时为空队列,都指向第一个元素
pos[front] = tree;
rear++;//对尾指针偏移一位,用于存放新数据
while(pos[front] != NULL){
printf("%c ", pos[front]->data);
if(pos[front]->l_child != NULL){
pos[rear] = pos[front]->l_child;//左孩子节点入队
rear++;
}
if(pos[front]->r_child != NULL){
pos[rear] = pos[front]->r_child;//右孩子节点入队
rear++;//尾指针偏移
}
front++;//头指针偏移一位判断下一个元素
}
}
关于二叉树的初步学习到这里就结束啦!
已经到底啦!!