关于二叉树,出现的印象一般就是一个“丫”字,这看似没有毛病,但其实也真没有什么毛病,逻辑上的二叉树差不多就是这个样子。可是当我们已经在逻辑上构建好了二叉树之后,真的不想去动手实现实现二叉树嘛?
下面,献上我的二叉树,仅供参考使用。
一、二叉树的构建
头文件.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<math.h>
typedef int HPDateType;
typedef struct Bintry
{
HPDateType date;
struct Bintry* left;
struct Bintry* right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
//n,pi都保存着字符串的长度
BTNode* BinaryTreeCreate(char* a, int n, int* pi);
//创建一个结点
BTNode* BuyNode(HPDateType data);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
//前序遍历
void PrevOrder(BTNode* root);
//中序遍历
void InOrder(BTNode* root);
//后序遍历
void PostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
函数库文件.c
#define _CRT_SECURE_NO_WARNINGS
#include"Order.h"
// 通过前序遍历的数组,如"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(char* a, int n, int* pi)
{
assert(a);
if (a[n-*pi] == '#')
{
return NULL;
}
else
{
BTNode* root = (BTNode*)malloc(sizeof(BTNode));
root->date = a[n-*pi];
(*pi)--;
root->left = BinaryTreeCreate(a, n, pi);
(*pi)--;
root->right= BinaryTreeCreate(a, n, pi);
return root;
}
}
//创建一个结点
BTNode* BuyNode(HPDateType data)
{
BTNode* root = (BTNode*)malloc(sizeof(BTNode));
if (root == NULL)
{
perror("malloc fail");
exit(-1);
}
root->date = data;
root->left = NULL;
root->right = NULL;
return root;
}
// 二叉树销毁
//后序遍历销毁
void BinaryTreeDestory(BTNode** root)
{
if((*root)->left != NULL)
{
BinaryTreeDestory(&((*root)->left));
}
if ((*root)->right != NULL)
{
BinaryTreeDestory(&((*root)->right));
}
if ((*root)->left == NULL && (*root)->right == NULL)
{
free(*root);
*root = NULL;
return;
}
}
//前序遍历
void PrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->date);//打印根结点
PrevOrder(root->left);
PrevOrder(root->right);
}
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->date);//打印根结点
InOrder(root->right);
}
//后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->date);//打印根结点
}
// 层序遍历
//层序遍历时若拥有栈,队列等数据结构,建议使用于sr1,sr2
void BinaryTreeLevelOrder(BTNode* root)
{
int h = TreeHight(root);
BTNode** sr1 = (BTNode**)malloc(sizeof(BTNode*) *(pow(2,h-1)) );
BTNode** sr2 = (BTNode**)malloc(sizeof(BTNode*) *(pow(2,h-1)) );
sr1[0] = root;
for (int j = 0; j < h; j++)
{
for (int i = 0; i < pow(2,j); i++)
{
if ((sr1[i]) == NULL)
{
printf("NULL ");
}
else
{
printf("%d ", sr1[i]->date);
}
if (j < h - 1)
{
sr2[i * 2] = (sr1[i]) != NULL ? sr1[i]->left : NULL;
sr2[i * 2 + 1] = (sr1[i]) != NULL ? sr1[i]->right : NULL;
}
}
BTNode** temp = sr1;
sr1 = sr2;
sr2 = temp;
}
printf("\n");
free(sr1);
free(sr2);
}
以上是二叉树的基本构建,原理大部分是递归,除了层序遍历。
二、二叉树的功能函数
这里就是二叉树这个数据结构的一些基本功能函数,毕竟不能光有数据,不能使用吧
注意,此部分只是为了方便讲解,如果要使用,需要与上部分代码进行合并。
头文件.h
typedef int HPDateType;
typedef struct Bintry
{
HPDateType date;
struct Bintry* left;
struct Bintry* right;
}BTNode;
//计算二叉树结点的数量
int TreeSize(BTNode* root);
//计算叶子结点个数
int TreeLeafSize(BTNode* root);
//计算二叉树的高度
int TreeHight(BTNode* root);
//计算第k层的结点个数
int TreeKSize(BTNode* root, int k);
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, HPDateType x);
函数库文件.c
//计算二叉树结点的数量
int TreeSize(BTNode* root)
{
return root!=NULL?TreeSize(root->left) + TreeSize(root->right)+1:0;
}
//计算叶子结点个数
int TreeLeafSize(BTNode* root)
{
if(root==NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
//计算二叉树的高度
int TreeHight(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int TreeHightLeft = TreeHight(root->left);
int TreeHightRight = TreeHight(root->right);
return TreeHightLeft > TreeHightRight ? TreeHightLeft+1: TreeHightRight +1;
}
//计算第k层的结点个数
int TreeKSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return TreeKSize(root->left, k - 1) + TreeKSize(root->right, k - 1);
}
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
int h = TreeHight(root);
BTNode** sr1 = (BTNode**)malloc(sizeof(BTNode*) *(pow(2,h-1)) );
BTNode** sr2 = (BTNode**)malloc(sizeof(BTNode*) *(pow(2,h-1)) );
sr1[0] = root;
for (int j = 0; j < h; j++)
{
int _or = 0;
for (int i = 0; i < pow(2,j); i++)
{
if ((sr1[i]) == NULL)
{
_or=1;
}
if(_or && (sr1[i]!=NULL))
{
return false;
break;
}
if (j < h - 1)
{
sr2[i * 2] = (sr1[i]) != NULL ? sr1[i]->left : NULL;
sr2[i * 2 + 1] = (sr1[i]) != NULL ? sr1[i]->right : NULL;
}
}
BTNode** temp = sr1;
sr1 = sr2;
sr2 = temp;
}
free(sr1);
free(sr2);
return true;
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, HPDateType x)
{
if (root == NULL)
{
return NULL;
}
if (root->date == x)
{
return root;
}
BTNode* a=BinaryTreeFind(root->left, x);
if (a)
{
return a;
}
BTNode* b=BinaryTreeFind(root->right, x);
if (b)
{
return b;
}
return NULL;
}
至此,便是我遇见二叉树,了解二叉树,实现二叉树,使用二叉树的过程。简单的展示一下,详解需等后续。