数据结构就是定义出某种结构:像数组结构、链表结构、树形结构等,实现数据结构就是我们主动去管理增删查改的实现函数
理解树的概念
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,它是根朝上,而叶朝下的
树的相关特征
节点的度:一个节点含有的子树的个数称为该节点的度,如上图:A的为6
叶节点或终端节点:度为0的节点称为叶节点,如上图:B、C、H、I...
非终端节点或分支节点:度不为0的节点,如上图:D、E、F、G...
双亲节点或父节点:节点含有子节点,节点就称为其子节点的父节点, 上图:A是B的父节点
孩子节点或子节点:含有的子树的根节点称为该节点的子节点,上图:B是A的孩子节点
兄弟节点:具有相同父节点的节点互称为兄弟节点,如上图:B、C是兄弟节点
树的度:一棵树中,最大的节点的度称为树的度;如上图:树的度为6
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次;如上图:树的高度为4
堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙:以某节点为根的子树中任一节点都称为该节点的子孙,图中:所有节点都是A的子孙
森林:由m(m>0)棵互不相交的树的集合称为森林;
二叉树的表示方法
二叉树非空的话是由根节点,根节点的左子树、根节点的右子树组成的
typedef int BTDateType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* left;//左子树
struct BinaryTreeNode* right;//右子树
BTDateType data;//节点域
}BTNode;
二叉树的遍历方法
用代码实现二叉树的基本操作前,我们先按照上图先申请6个节点创建一棵二叉树
//定义函数
typedef int BTDateType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* left;//定义左子树节点
struct BinaryTreeNode* right;//定义右子树节点
BTDateType data;
}BTNode;
//申请节点函数
BTNode* BuyBTNode(BTDateType x)//按照上图申请6节点
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL)
{
printf("malloc fail\n");
exit(-1);
}
node->data = x;
node->left = node->right = NULL;
return node;//...
}
//树的创建
BTNode* CreatBinaryTree()//先自己创建树
{
BTNode* node1 = BuyBTNode(1);
BTNode* node2 = BuyBTNode(2);
BTNode* node3 = BuyBTNode(3);
BTNode* node4 = BuyBTNode(4);
BTNode* node5 = BuyBTNode(5);
BTNode* node6 = BuyBTNode(6);
node1->left = node2;//这里按照上图指向指定数据
node1->right = node4;
node2->left = node3;
node4->left = node5;
node4->right = node6;
return node1;//根是node1
}
二叉树的前序遍历
//前序遍历(先根遍历) 根 左子树 右子树
void PreOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");//
return;
}
//根不为空的话
printf("%d ", root->data);//打印根数据
PreOrder(root->left);//走左子树
PreOrder(root->right);//再走右子树
}
二叉树的中序遍历
//中序遍历(中根遍历) 左子树 根 右子树
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");//
return;
}
//根不为空的话
InOrder(root->left);//走左子树
printf("%d ", root->data);//打印根数据
InOrder(root->right);//再走右子树
}
二叉树的后序遍历
//后序遍历(后根遍历) 左子树 右子树 根
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");//
return;
}
//根不为空的话
PostOrder(root->left);//走左子树
PostOrder(root->right);//再走右子树
printf("%d ", root->data);//打印根数据
}
二叉树的节点个数
//打印节点个数 有多少个值
//思想方法 子问题 分治思想
int BTreeSize(BTNode* root)
{
//不是空 左节点+右节点+1
return root == NULL ? 0 :
BTreeSize(root->left)
+ BTreeSize(root->right)+1;
}
二叉树求叶子节点个数
//求叶子节点个数
int BTreeLeafSize(BTNode* root)
{
if (root == NULL)
return 0;
if (root->left == NULL && root->right == NULL)
return 1;
return BTreeLeafSize(root->left)
+ BTreeLeafSize(root->right);
}
二叉树第k层节点个数
//求第k层的节点个数 k=1
int BTtreekLeveSize(BTNode* root, int k)
{
assert(k >= 1);
//空树 是0
if (root == NULL)
return 0;
//非空且k==1 返回1
if (k == 1)
return 1;
//非空且k>1 转换求左子树k-1层+右子树k-1层节点个数
return BTtreekLeveSize(root->left, k - 1)
+ BTtreekLeveSize(root->right, k - 1);
}
二叉树查找值为x的节点
//查找值是x的节点 返回节点指针(地址)同时可修改
BTNode* BTreeFind(BTNode* root, BTDateType x)
{
//..不一定一开始是空
if (root == NULL)
return NULL;
//先从根找
if (root->data == x)
return root;
// 递归左数找
BTNode* ret1 = BTreeFind(root->left, x);
if (ret1)
{
return ret1;
}
// 左数没有 递归右数找
BTNode* ret2 = BTreeFind(root->right, x);
if (ret2)
{
return ret2;
}
//都没有返回空
return NULL;
}
编程实现二叉树的深度
//求二叉树深度
int BTreeDepth(BTNode* root)
{
//左子树高度和右子树高度,大的加1
if (root == NULL)
return 0;
//递归分别求左右深度
int leftDepth = BTreeDepth(root->left);
int rightDepth = BTreeDepth(root->right);
// 返回高度大的+1
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
编程实现二叉树的销毁
//销毁 后序遍历 置空二级
void BTreeDestroy(BTNode* root)
{
if (root == NULL)
{
return;
}
// 先删左数 再删右数 最后删根
BTreeDestroy(root->left);
BTreeDestroy(root->right);
free(root);
root = NULL;
}
上面的方法测试案例
int main()
{
BTNode* tree = CreatBinaryTree();
//遍历
PreOrder(tree);//前序
printf("\n");//1 2 3 NULL NULL NULL 4 5 NULL NULL 6 NULL NULL
InOrder(tree);//中序
printf("\n");//NULL 3 NULL 2 NULL 1 NULL 5 NULL 4 NULL 6 NULL
PostOrder(tree);//后序
printf("\n");//NULL NULL 3 NULL 2 NULL NULL 5 NULL NULL 6 4 1
printf("size:%d\n", BTreeSize(tree));//6
printf("leafsize:%d\n", BTreeLeafSize(tree));//3
printf("kleafsize:%d\n", BTtreekLeveSize(tree,3));//
printf("Depth:%d\n", BTreeDepth(tree));//3
//查找6个节点 返回地址
//程序对不对 要靠测试来检验的
for (int i = 1; i < 7; i++)
{
printf("Find:%d,%p\n", i,BTreeFind(tree, i));
}
BTreeDestroy(tree);//销毁
tree = NULL;
return 0;
}
在Java和C++的学习当中,前期学习数据结构当中的顺序表、链表、二叉树等便于我们后面更好的学习容器,后面会继续分享搜索二叉树和算法的实现
希望这篇文章大家有所收获,我们下篇见