目录
很简单,对于二叉树链式结构,我们需要先建立一个二叉树——简单地用到链式结构
typedef int BTDataType;
typedef struct BinaryTreeNode//结构体嵌套结构体的代码
{
BTDataType data;
struct BinaryTreeNode* left;//左树
struct BinaryTreeNode* right;//右树
}BTNode;
BTNode* BuyNode(BTDataType x)
{
BTNode* node=(BTDataType*)malloc(sizeof(BTNode));//创建一个结构体大小的数据
if(node==NULL)//判断是否创建成功
{
perror("malloc fail");
return ;
}
node->data=x;//创建的数据存放x,两个子树初始化
node->left=NULL;
node->right=NULL;
return node;
}
BTNode* CreatBinaryTree()//创建一个简单的树
{
BTNode* node1 = BuyNode(1);
BTNode* node2 = BuyNode(2);
BTNode* node3 = BuyNode(3);
BTNode* node4 = BuyNode(4);
BTNode* node5 = BuyNode(5);
BTNode* node6 = BuyNode(6);
BTNode* node7 = BuyNode(7);
node1->left = node2;
node1->right = node4;
node2->left = node3;
node4->left = node5;
node4->right = node6;
node5->left = node7;
return node1;
}
但这不是创建二叉树的真正方式
我们需要用到
层序遍历
设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
可以粗略的约等于一个元素的逐个遍历,但是每个元素也会遍历到其指向的左右子树
——本质上也还能算是一个递归的实现
为了实现层序遍历,我们需要用到队列—(先进后出的数据结构)
在队列中需要实现
1.元素的逐个放入
2.元素放入后的逐个读取,及其放入元素的左右子树
这样不仅实现根元素的读取,又能载入其左右子树,并且通过队列的删除,进行下一个元素的数据读取和下一个元素的左右子树的载入
void LevelOrder(BTNode* root)
{
Queue q;//创建一个结构体,并且进行初始化
QueueInit(&q);
if (root)
QueuePush(&q, root);//先第一个数据1
while (!QueueEmpty(&q))//若不为空,一个一个元素的过,但是打印是按照顺序的
{
BTNode* front = QueueFront(&q);//选定第一个数据,拿出来放入指针中,然后进行删除
//并且进行打印
QueuePop(&q);
printf("%d", front->data);//出来第一个根1
//左不为空,则带2出来
//打印前提是将数据放入数组q中,这样可以带出该组数据的左右子树
if (front->left)
QueuePush(&q, front->left);
//右不为空,带出4
if (front->right)
QueuePush(&q, front->right);
//下一轮就到了2,然后打印,再对2的左右进行遍历
}
printf("\n");
QueueDestroy(&q);
}
Tips
遍历的所有基本概念都围绕着根——左子树——右子树的顺序,存放在队列(数列)里也会是按照根——左子树——右子树顺序存放,我们接下来二叉树链式结构的实现,都会用到这样的递归思想
节点个数
由左右子树决定该节点承载的节点数
int BTreeSize(BTNode* root)
{
if(root==NULL)
return 0;
return BTreeSize(root->left)+BTreeSize(root->right)+1;
}
解释如下:
二叉树叶子节点个数
思维同求全部节点的个数——由下方结点统计数量后再将数据归到最上层
叶子结点——度为0的结点,那么仅需要判断其左右子树为NULL即可
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层的数据
仍使用递归的思想,下层数据传递到上层
int BTreeLeafKSize(BTNode* root,int k)
{
if(root==NULL)
{
return 0;
}
if(k==1)
{
return 1;
}
return BTreeLeafKSize(root->left,k-1)+BTreeLeafKSize(root->right,k-1);
}
查找值为x的节点
BTNode* BTreeFind(BTNode* root, BTDataType x)
{
if(root==NULL)
return NULL
if(root->data==x)
return root;
BTNode* ret1=BTreeFind(root->left,x);
if(ret1->data==x)
return ret1;
BTNode* ret2=BTreeFind(root->right,x);
if(ret2->data==x)
return ret2;
return NULL:
}
同理,此处并不是从左右子树共同出发,而是先遍历完左树后再去遍历右树
然后用一个变量去保存,如果直接检验的话会造成数据的丢失
二叉树的高度
int BTreeHeight(BTNode* root)
{
if(root==NULL)
return 0;
int LeftHeight=BTreeHeight(root->left);
int RightHeight=BtreeHeight(root->right);
return LeftHeight>RightHeight?LeftHeight+1:RightHeight+1;
}
本质其实就是统计出最后每一个分支的最大的节点数,便是二叉树的高度。
读到NULL就会返回0,说明此结点往后没有任何结点,然后便是要加上1,就是节点本身要计数