《数据结构——二叉树》

目录

1.1 定义

2.2 二叉树相关概念

2.3 二叉树的五种状态

2.4 二叉树的性质

2.5 二叉树存储

2.6 节点结构体类型

2.7 创建:先序创建

2.7 先序遍历

2.8 中序遍历

2.9 后续遍历

代码实现↓

bitree.h

bitree.c

main.c


1.1 定义

每个节点最多有两棵子树,并且严格区分左右的树形结构

2.2 二叉树相关概念

【左子树】左子树是以当前结点的左孩子结点作为根节点的子树 【右子树】右子树是以当前结点的右孩子结点作为根节点的子树 【满二叉树】满二叉树是最后一层是叶子结点,其余结点度是2的二叉树 在不增加层次的基础上,不能在添加节点的二叉树 【完全二叉树】完全二叉树是在一棵满二叉树基础上自左向右连续增加叶子结点得到的二叉树 完全二叉树是在一棵满二叉树基础上自右向左连续删除叶子结点得到的二叉树

2.3 二叉树的五种状态

空二叉树、只有根结点、只有左子树、只有右子树、既有左子树也有右子树

2.4 二叉树的性质

性质1:在二叉树的第i层上最多有2^(i-1)个结点(i >= 1)

性质2:深度为k的二叉树最多有2^k-1个结点(k >= 1)

性质3:在任意一棵二叉树中,叶子结点的数目比度数为2的结点的数目多一

假设 n0:度数为0的所有节点的个数
    n1:度数为1的所有节点的个数
     n2:度数为2的所有节点的个数
    
    总度数 = 总结点个数 - 1
    总个数 = n0 + n1 + n2;
    总度数 = 2*n2 + n1
     
           
     最终结果:n2 = n0 - 1
性质4:如果第i个节点存在左孩子,那么其左孩子应该在树中第2*i个位置
      如果第i个节点存在右孩子,那么其右孩子应该在树中第2*i+1个位置

2.5 二叉树存储

1> 顺序存储:由于在二叉树的存储中,空节点也要占一个位置,导致会浪费大量的空间,所以,存储二叉树,不常使用顺序存储 ​ 2> 链式存储:

2.6 节点结构体类型

typedef char datatype;
typedef struct Node
{
    datatype data;            //数据域
    struct Node *left;        //指向左子树的指针
    struct Node *right;       //指向右子树的指针
}biTree;

2.7 创建:先序创建

先创建根节点、接着创建左子树、最后创建右子树

biTree *tree_create()
{
    //定义一个字符数据,存放用户输入的数据
    char ch = '\0';
    
    scanf("%c", &ch);
    getchar();
​
    if(ch == '!')    //如果是‘!’说明空节点
    {
        return NULL;
    }
​
    //申请节点保存数据
    biTree *B = (biTree *)malloc(sizeof(biTree));
    if(NULL==B)
    {
        printf("空间申请失败\n");
        return NULL;
    }
​
    B->data = ch;      //将数据存入节点
​
    B->left = tree_create();   //递归创建左子树
    B->right = tree_create();  //递归创建右子树
​
    return B;       //将创建好的树,返回
}

2.7 先序遍历

也称先根遍历,先访问根节点中的内容,然后访问左子树、最后访问右子树

void pri_order(biTree *B)
{
      if(NULL==B)
      {
         return ;
      }
      printf("%c\t", B->data);   //先访问根节点
      pri_order(B->left);      //先序遍历左子树
      pri_order(B->right);      //先序遍历右子树
}
​

2.8 中序遍历

也称中根遍历,先访问左子树、然后访问根节点内容、最后访问右子树

void in_order(biTree *B)
{
      if(NULL==B)
      {
         return ;
      }
      in_order(B->left);      //中序遍历左子树
​
      printf("%c\t", B->data);   //访问根节点
​
      in_order(B->right);      //中序遍历右子树
}

2.9 后续遍历

也称后根遍历,先访问左子树、然后访问右子树、最后访问根节点内容

void post_order(biTree *B)
{
      if(NULL==B)
      {
         return ;
      }
      post_order(B->left);      //后序遍历左子树
​
      post_order(B->right);      //后序遍历右子树
​
      printf("%c\t", B->data);   //访问根节点
}

代码实现↓

bitree.h

#ifndef __BITREE_H__
#define __BITREE_H__

typedef int datatype;
typedef struct Node
{
	datatype data;
	struct Node *L;
	struct Node *R;
}bitree;

//创建
bitree *create();
//先序遍历
void pri_order(bitree *B);
//中序遍历
void in_order(bitree *B);
//后序遍历
void post_order(bitree *B);
#endif

bitree.c

#include<stdlib.h>
#include"bitree.h"
#include<stdio.h>
//创建
bitree *create()
{
	char val=0;
	printf("请输入:");
	scanf("%c",&val);
	getchar();   //吸收回车
	if (val=='#')
	{
		return NULL;
	}
	bitree *p=(bitree *)malloc(sizeof(bitree));
	if (NULL==p)
	{
		printf("申请失败\n");
		return NULL;
	}
	p->data=val;
	p->L=create();//建立左子树
	p->R=create();//建立右子树
	return p;
}
//先序遍历
void pri_order(bitree *B)
{
	if (NULL==B)
	{
		return ;
	}
	//访问根节点
	printf("%c\t",B->data);
	//先序遍历左子树
	pri_order(B->L);
	pri_order(B->R);
}
//中序遍历
void in_order(bitree *B)
{
	if (NULL==B)
	{
		return ;
	}
	//先遍历左子树
	pri_order(B->L);
	//访问根节点
	printf("%c\t",B->data);
	//遍历右子树
	pri_order(B->R);
}
//后序遍历
void post_order(bitree *B)
{
	if (NULL==B)
	{
		return ;
	}
	//先遍历左子树
	pri_order(B->L);
	//遍历右子树
	pri_order(B->R);
	//访问根节点
	printf("%c\t",B->data);
}

main.c

#include<stdlib.h>
#include"bitree.h"
#include<stdio.h>
int main(int argc, const char *argv[])
{
	bitree *B=create();
	if (NULL==B)
	{
		return -1;
	}
	printf("创建成功\n");
	//先序遍历函数
	printf("先序遍历\n");
	pri_order(B);
	printf("\n");
	//中序遍历函数
	printf("中序遍历\n");
	pri_order(B);
	printf("\n");
	//后序遍历函数
	printf("后序遍历\n");
	pri_order(B);
	printf("\n");
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值