【整理】二叉树概念以及代码实现

1 二叉树
 1.1 相关概念
  在计算机中,二叉树是指每个节点最多只有两个子节点的树形结构
  × 其中起始的节点叫做根节点,整棵树只有一个根节点,除了根节点之外,每个节点都有且只有一个父节点
  × 其中没有任何子节点的节点叫做叶子节点,除了叶子节点之外,每个节点最多只有两个子节点,也就是说叶子节点只有父节点,没有子节点
  × 除了根节点和叶子节点之外,剩下的节点叫做枝节点,枝节点有父节点也有子节点
  × 如果该二叉树中每层节点均达到最大值,也就是每个枝节点都有两个子节点,则该二叉树叫做满二叉树
  × 如果该二叉树中除了最下面一层之外,每层节点个数均达到最大值,并且最下面一层的节点都连续集中在左侧,则该二叉树叫做完全二叉树

 1.2 基本的特征
  二叉树具有递归嵌套式的空间结构,也就是说对于一棵二叉树来说,可以拆分为若干个小二叉树组成,因此采用递归的方法处理二叉树比较方便
  处理方式如下:
    处理(二叉树)
   {
     if(是空树)  直接处理完毕
     else
     {
       处理根节点;
       处理左子树;  => 递归
       处理右子树;  => 递归
     }
   } 
 1.3 二叉树的存储结构
  (1)顺序存储结构
    一般来说, 从上到下, 从左到右依次存储节点,对于非完全二叉树来说,采用虚节点来补成完全二叉树
  (2)链式存储结构
    一般来说,每个节点中除了存储数据元素本身之外,还需要两个指针,分别记录左右子节点的地址
    如:
     typedef struct Node
     {
       int data; // 数据内容
       struct Node *left; // 记录左子树的地址
       struct Node *right; //记录右子树的地址
     }Node;
 
 1.4 基本操作
  创建、销毁、插入新元素、删除元素、查找指定的元素、修改指定的元素、判断二叉树是否为满、判断二叉树是否为空、计算二叉树节点的个数、获取根节点的元素值、遍历
 
 1.5 二叉树的遍历方式
  (1) 先序遍历(DLR - data left right)
   先遍历根节点,再遍历左子树,最后遍历右子树,又叫做先根遍历
  (2) 中序遍历(LDR - left data right) ** ( 重点 )
   先遍历左子树,再遍历根节点,最后遍历右子树,又叫做中根遍历
  (3) 后序遍历(LRD - left right data)
   先遍历左子树,再遍历右子树,最后遍历根节点,又叫做后根遍历
 
 1.6 有序二叉树
  一般来说,当左子树不为空时,则左子树的元素值小于等于根节点;当右子树不为空时,则右子树的元素值大于等于根节点,左右子树也分别有序,满足上述特征的二叉树,叫做有序二叉树。

***********************************************************************************
有序二叉树的代码实现:
#include <stdio.h>
#include <stdlib.h>

//定义节点的数据类型
typedef struct Node
{
	int data;  // 存储数据内容
	struct Node *left;	// 左子树的地址
	struct Node *right;	// 右子树的地址
} Node;

//定义有序二叉树的数据类型
typedef struct
{
	Node *root;	// 记录根节点的地址
	int cnt;	//记录节点的个数
}Tree;

//实现向有序二叉树中插入新节点的操作
void insert_data(Tree *pt, int data);
// 插入新节点的递归函数
void insert(Node **pRoot, Node *pn);
//采用中序遍历方法进行遍历
void travel_data(Tree *pt);
//遍历的递归函数
void travel(Node *pRoot);
//创建节点
Node *create_node(int data);
//清空二叉树节点
void clear_data(Tree *pt);
//递归清除节点
void clear(Node **pRoot);
//删除功能
void del_data(Tree *tp, int data);


int main(void)
{
	//创建有序二叉树,并且进行初始化
	Tree tree;
	tree.root = NULL;
	tree.cnt = 0;
	//插入新节点,进行遍历
	insert_data(&tree, 50);
	travel_data(&tree);  // 50
	insert_data(&tree, 70);
	travel_data(&tree);  // 50 70
	insert_data(&tree, 20);
	travel_data(&tree);  // 20 50 70
	insert_data(&tree, 60);
	travel_data(&tree);  // 20 50 60 70
	printf("二叉树中节点个数:%d\n", tree.cnt);
	clear_data(&tree);
	travel_data(&tree);
	printf("二叉树中节点个数:%d\n", tree.cnt);
	return 0;
}

Node **del(Node *pRoot, int data)
{
	if (pRoot->data == data)
	{
		return &pRoot;
	}
	if (pRoot->left != NULL)
	{
		del(pRoot->left, data);
	}
	if (pRoot->right != NULL)
	{
		del(pRoot->right, data);
	}
}

//删除功能
void del_data(Tree *pt, int data)
{	
	Node **del(pt->root, data);
	
}

//递归清除节点
void clear(Node **pRoot)
{
	if ((*pRoot)->left == NULL && (*pRoot)->right == NULL)
	{
		free(*pRoot);
		*pRoot = NULL;
		return;
	}
	if ((*pRoot)->left != NULL)
	{
		clear(&(*pRoot)->left);
	}

	if ((*pRoot)->right != NULL)
	{
		clear(&(*pRoot)->right);
	}
}

//清空二叉树节点
void clear_data(Tree *pt)
{
	if (pt->root == NULL)
	{
		return;
	}
	while (pt->root != NULL)
	{
		clear(&pt->root);
	}
	pt->cnt = 0;
}

//创建节点
Node *create_node(int data)
{
	Node *pn = (Node *)malloc(sizeof(Node));
	pn->data = data;
	pn->left = NULL;
	pn->right = NULL;
}

//遍历的递归函数
void travel(Node *pRoot)
{
	//判断二叉树不为空时才需要遍历
	if (pRoot != NULL)
	{
		//1.遍历左子树
		travel(pRoot->left);
		//2.遍历根节点
		printf("%d ", pRoot->data);
		//3.遍历右子树
		travel(pRoot->right);
	}
}

//采用中序遍历方法时行遍历
void travel_data(Tree *pt)
{
	//调用递归函数进行遍历
	travel(pt->root);
	printf("\n");
}

// 插入新节点的递归函数
void insert(Node **pRoot, Node *pn)
{
	//1.判断二叉树是否为空,如果为空则让根节点指针直接指向新节点
	if (NULL == *pRoot)
	{
		*pRoot = pn;
		return;
	}
	//2.如果二叉树不为空,比较根节点和新节点大小
	//2.1如果根节点大于新节点,插入左子树
	if ((*pRoot)->data > pn->data)
	{
		insert(&(*pRoot)->left, pn);
	}
	//2.2如果根节点小于等于新节点,插入右子树
	else 
	{
		insert(&(*pRoot)->right, pn);
	}

}

//实现向有序二叉树中插入新节点的操作
void insert_data(Tree *pt, int data)
{
	//1.创建新节点,进行初始化
	//Node *pn = (Node *)malloc(sizeof(Node));
	//pn->data = data;
	//pn->left = NULL;
	//pn->right = NULL;
	Node *pn = create_node(data);
	//2.插入新节点到二叉树中,调用递归函数
	insert(&pt->root, pn);
	//3.二叉树中节点个数加1
	pt->cnt++;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值