首先总结一下二叉树的各个接口函数:
二叉树的接口函数实现是明细要比前面学过的数据结构难的,所以这里全部列出来,然后给定代码,这些接口函数中,只有最后两个在前面的文章或者OJ当中还没出现:层序遍历和判断是否完全二叉树,其他的接口函数都已经出现过,下文撰写层序遍历和判断是否完全二叉树除了仅列出:
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi);
BTNode* BuyNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
assert(node);
node->data = x;
node->left = NULL;
node->right = NULL;
return node;
}
BTNode* BinaryTreeCreate(BTDataType* a int* pi);
{
if(str[*pi]=='#')
{
(*pi)++;
return NULL;
}
BTNode*root=BuyNode(str[(*pi)++]);
root->left=CreateTree(str,pi);
root->right=CreateTree(str,pi);
return root;
}
int main()
{
char str[100];
scanf("%s",str);
int i=0;
BTNode*root=BinaryTreeCreate(str, &i);
return 0;
}
二叉树销毁
void BinaryTreeDestory(BTNode* root)
{
if(root==NULL)
return;
BinaryTreeDestory(root->left);
BinaryTreeDestory(root->right);
free(root);
}
二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
if(root==NULL)
return 0;
return BinaryTreeSize(root->left)+ BinaryTreeSize(root->right) + 1;
}
二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
return 0;
if (root->left== NULL && root->right == NULL)
return 1;
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
assert(k >= 1);
if (root == NULL)
return 0;
if (k == 1)
return 1;
return BinaryTreeLevelKSize(root->left, k - 1)
+ BinaryTreeLevelKSize(root->right, k - 1);
}
二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
return NULL;
if (root->data == x)
return root;
BTNode* ret1 = BinaryTreeFind(root->left, x);
if (ret1)
return ret1;
BTNode* ret2 = BinaryTreeFind(root->right, x);
if (ret2)
return ret2;
return NULL;
}
二叉树前序遍历
int TreeSize(struct TreeNode*root)
{
return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}
void preorder(struct TreeNode* root,int *a,int* pi)
{
if(root==NULL)
return ;
a[(*pi)++]=root->val;
preorder(root->left,a,pi);
preorder(root->right,a,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize=TreeSize(root);
int *a=(int *)malloc(*returnSize*sizeof(int));
int i=0;
preorder(root,a,&i);
return a;
}
二叉树中序遍历
int TreeSize(struct TreeNode*root)
{
return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}
void InOrder(struct TreeNode* root,int*a,int* pi)
{
if(root==NULL)
return ;
InOrder(root->left,a,pi);
a[(*pi)++]=root->val;
InOrder(root->right,a,pi);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
* returnSize=TreeSize(root);
int* a=(int*)malloc(sizeof(int)**returnSize);
int i=0;
InOrder(root,a,&i);
return a;
}
二叉树后序遍历
int TreeSize(struct TreeNode*root)
{
return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}
void InOrder(struct TreeNode* root,int*a,int* pi)
{
if(root==NULL)
return ;
InOrder(root->left,a,pi);
InOrder(root->right,a,pi);
a[(*pi)++]=root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
* returnSize=TreeSize(root);
int* a=(int*)malloc(sizeof(int)**returnSize);
int i=0;
InOrder(root,a,&i);
return a;
}
以上这三个都是一个道理。
层序遍历,这是一种广度优先遍历的方式
思路:利用队列来做,下图举例子
创建一个队列,先进1,保存队头,再出1,然后2和3进,保存队头2,出2,进4和5,再保存队头3,出3,保存队头4.......直到遍历完成。
void BinaryTreeLevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
printf("%d ",front->data);
QueuePop(&q);
if (front -> left)
{
QueuePush(&q, front->left);
}
if (front -> left)
{
QueuePush(&q, front->right);
}
}
printf("\n");
QueueDestroy(&q);
}
判断二叉树是否是完全二叉树
这个其实就是再层序遍历上来做,如果队列的front出现空,且后续层序遍历全是空,则是完全二叉树,若front出现空之后,后续有非空元素出现,则不是完全二叉树。
// 判断二叉树是否是完全二叉树
//核心思路:层序遍历时,把空也入队列。
//完全二叉树,非空是连续
//不是完全二叉树,非空不是连续
bool BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if(root)//先入队根节点
{
QueuePush(&q,root);
}
while(!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);//取队头,将它保存起来
QueuePop(&q);//出队
if(front==NULL)
{
break;//遇到空就跳出循环
}
//不管是不是NULL都入队
QueuePush(&q,front->left);
QueuePush(&q,front->right);
}
// 出到空以后,队列中全是空,就是完全二叉树
// 还有非空,就不是完全二叉树
while(!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);//取队头,将它保存起来
QueuePop(&q);//出队
if(front)
{
QueueDestory(&q);
return false;
}
}
//走到这里说明队列后面是连续的空,故是完全二叉树
QueueDestory(&q);
return true;
}