本篇主要实现了二叉树的创建、前中后序遍历(递归以及非递归)、层序遍历、判断一个二叉树是否是完全二叉树、查找第一次匹配的结点以及求叶子结点个数和树的高度等等。
头文件
1、tree.h
# ifndef __TREE_H__
# define __TREE_H__
# include <stdio.h>
# include <assert.h>
# include <stdlib.h>
# define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
typedef char DataType;
typedef struct BinaryTreeNode
{
DataType data;
struct BinaryTreeNode * pLeft;
struct BinaryTreeNode * pRight;
}BTNode;
BTNode * BuildTree(DataType array[], int size, int * pIndex); // 生成二叉树
void PreOrder(BTNode * pRoot); // 前序遍历递归
void PreOrderLoop(BTNode * pRoot); // 前序遍历非递归
void InOrder(BTNode * pRoot); // 中序遍历递归
void InOrderLoop(BTNode * pRoot); // 中序遍历非递归
void PostOrder(BTNode * pRoot); // 后序遍历递归
void PostOrderLoop(BTNode * pRoot); // 后序遍历非递归
void LevelOrder(BTNode * pRoot); // 层序遍历
int TreeSize(BTNode * pRoot); // 树的结点数
int LeafSize(BTNode * pRoot); // 叶子结点数
int GetKSize(BTNode * pRoot, int k); // 求第k层结点数
int GetHeight(BTNode * pRoot); // 树的高度
BTNode * Find(BTNode * pRoot, DataType data); // 查找第一次匹配的结点,若找到该结点则返回结点地址,反之则返回NULL
int IsComplete(BTNode * pRoot); // 判断当前二叉树是否是完全二叉树,假如是则返回1,反之则返回0
# endif // __TREE_H__
2、queue.h
# ifndef __QUEUE_H__
# define __QUEUE_H__
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
typedef void * QDataType;
typedef struct QNode
{
QDataType data;
struct QNode * pNext;
}QNode, * pQNode;
typedef struct Queue
{
pQNode pFront;
pQNode pRear;
int size;
}Queue, * pQueue;
void QueueInit(pQueue pQ); // 队列的初始化
void QueuePush(pQueue pQ, QDataType data); // 入队
void QueuePop(pQueue pQ); // 出队
QDataType QueueFront(pQueue pQ); // 取队首元素
int QueueIsEmpty(pQueue pQ); // 队列判空
void QueueDestory(pQueue pQ); // 销毁队列
# endif // __QUEUE_H__
3、stack.h
# ifndef _STACK_H__
# define _STACK_H__
# include <stdio.h>
# include <assert.h>
# include <string.h>
# include <stdlib.h>
# define MAX_SIZE (10)
typedef void * SDataType;
typedef struct Stack
{
SDataType data[MAX_SIZE]; // 存放栈的元素
int top; // 用于栈顶指针,类似于游标卡尺的游标
}Stack, *pStack;
void StackInit(pStack pS); // 栈的初始化
void StackPush(pStack pS, SDataType data); // 入栈
void StackPop(pStack pS); // 出栈
SDataType StackTop(pStack pS); // 获取栈顶元素
int StackIsEmpty(pStack pS); // 判断栈是否为空
void StackDestory(pStack pS); // 栈的销毁
# endif // _STACK_H__
难点剖析
1、如何判断一个二叉树是否是完全二叉树
层序遍历完全二叉树时,可以发现NULL接连出现(并且队列中只剩下NULL),假如该树不是完全二叉树,可以发现第一次出现NULL后,后边还会出现其他非NULL的结点,这时候只需要去判断队列中的元素是否全为NULL即可。
2、注意事项
层序遍历考虑用队列,非递归的前中后序遍历考虑用栈。
源代码
1、queue.c
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:queue.c
* 功能:链式队列内部实现细节
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年6月6日22:30:25
*/
# include "queue.h"
/*
* 函数名称:QueueInit
*
* 函数功能:队列的初始化
*
* 入口参数:pQ
*
* 出口参数:void
*
* 返回类型:void
*/
void QueueInit(pQueue pQ)
{
assert(NULL != pQ);
pQ->pFront = pQ->pRear = NULL;
pQ->size = 0;
return;
}
/*
* 函数名称:QueuePush
*
* 函数功能:入队
*
* 入口参数:pQ, data
*
* 出口参数:void
*
* 返回类型:void
*/
void QueuePush(pQueue pQ, QDataType data)
{
pQNode pNewNode = NULL;
assert(NULL != pQ);
pNewNode = (pQNode)malloc(sizeof(QNode));
assert(NULL != pNewNode);
pQ->size++;
if (NULL == pQ->pFront)
{
pQ->pFront = pQ->pRear = pNewNode;
pNewNode->data = data;
pQ->pRear->pNext = NULL;
}
else
{
pNewNode->data = data;
pNewNode->pNext = NULL;
pQ->pRear->pNext = pNewNode;
pQ->pRear = pNewNode;
}
return;
}
/*
* 函数名称:QueuePop
*
* 函数功能:出队
*
* 入口参数:pQ
*
* 出口参数:void
*
* 返回类型:void
*/
void QueuePop(pQueue pQ)
{
pQNode pDelNode = NULL;
assert(NULL != pQ);
assert(NULL != pQ->pFront);
pQ->size--;
pDelNode = pQ->pFront;
pQ->pFront = pDelNode->pNext;
free(pDelNode);
if (NULL == pQ->pFront)
{
//pQ->pRear = NULL;
pQ->pRear = pQ->pFront;
}
else
{
;
}
return;
}
/*
* 函数名称:QueueFront
*
* 函数功能:取队首的元素
*
* 入口参数:pQ
*
* 出口参数:pQ->pFront->data
*
* 返回类型:QDataType
*/
QDataType QueueFront(pQueue pQ)
{
assert(NULL != pQ);
assert(NULL != pQ->pFront);
return pQ->pFront->data;
}
/*
* 函数名称:QueueIsEmpty
*
* 函数功能:队列判空
*
* 入口参数:pQ
*
* 出口参数:0 or 1
*
* 返回类型:int
*/
int QueueIsEmpty(pQueue pQ)
{
assert(NULL != pQ);
return 0 == pQ->size ? 1 : 0;
}
/*
* 函数名称:QueueDestory
*
* 函数功能:队列的销毁
*
* 入口参数:pQ
*
* 出口参数:void
*
* 返回类型:void
*/
void QueueDestory(pQueue pQ)
{
pQNode pCurNode = NULL;
pQNode pNextNode = NULL;
assert(NULL != pQ);
for (pCurNode = pQ->pFront; NULL != pCurNode; pCurNode = pNextNode)
{
pNextNode = pCurNode->pNext;
free(pCurNode);
}
pQ->pFront = pQ->pRear = NULL;
pQ->size = 0;
return;
}
2、stack.c
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:stack.c
* 功能:顺序栈的基本功能内部实现细节
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年6月2日20:19:45
*/
# include "stack.h"
/*
* 函数名称:StackInit
*
* 函数功能:栈的初始化,pS->top = 0表示空栈
*
* 入口参数:pS
*
* 出口参数:void
*
* 返回类型:void
*/
void StackInit(pStack pS)
{
assert(NULL != pS);
pS->top = 0;
return;
}
/*
* 函数名称:StackPush
*
* 函数功能:入(压)栈
*
* 入口参数:pS, data
*
* 出口参数:void
*
* 返回类型:void
*/
void StackPush(pStack pS, SDataType data)
{
assert(NULL != pS);
assert(pS->top < MAX_SIZE);
pS->data[pS->top++] = data;
return;
}
/*
* 函数名称:StackPop
*
* 函数功能:出栈
*
* 入口参数:pS
*
* 出口参数:void
*
* 返回类型:void
*/
void StackPop(pStack pS)
{
assert(NULL != pS);
assert(pS->top > 0);
pS->top--;
return;
}
/*
* 函数名称:StackTop
*
* 函数功能:获取栈顶元素
*
* 入口参数:pS
*
* 出口参数:void
*
* 返回类型:void
*/
SDataType StackTop(pStack pS)
{
assert(NULL != pS);
assert(pS->top > 0);
return pS->data[pS->top - 1];
}
/*
* 函数名称:StackIsEmpty
*
* 函数功能:判断栈是否为空
*
* 入口参数:pS
*
* 出口参数:1 or 0
*
* 返回类型:int
*/
int StackIsEmpty(pStack pS)
{
assert(NULL != pS);
return 0 == pS->top ? 1 : 0;
}
/*
* 函数名称:StackDestory
*
* 函数功能:栈的销毁
*
* 入口参数:pS
*
* 出口参数:void
*
* 返回类型:void
*/
void StackDestory(pStack pS)
{
assert(NULL != pS);
pS->top = 0;
return;
}
3、tree.c
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:tree.c
* 功能:二叉树的基本操作内部实现细节
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年6月13日22:30:27
*/
# include "tree.h"
# include "queue.h"
# include "stack.h"
/*
* 函数名称:BuildTree
*
* 函数功能:创建树
*
* 入口参数:array, size, pIndex
*
* 出口参数:pRoot or NULL
*
* 返回类型:BTNode *
*/
BTNode * BuildTree(DataType array[], int size, int * pIndex)
{
BTNode *pRoot = NULL;
assert(NULL != pIndex);
if (*pIndex >= size)
{
return NULL;
}
else if ( '#' == array[*pIndex])
{
(*pIndex)++;
return NULL;
}
else
{
pRoot = (BTNode *)malloc(sizeof(BTNode));
assert(pRoot);
pRoot->data = array[*pIndex];
(*pIndex)++;
pRoot->pLeft = BuildTree(array, size, pIndex);
pRoot->pRight = BuildTree(array, size, pIndex);
return pRoot;
}
}
/*
* 函数名称:PreOrder
*
* 函数功能:前序遍历(递归)
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void PreOrder(BTNode * pRoot)
{
if (NULL == pRoot)
{
return;
}
else
{
;
}
printf("%c ", pRoot->data);
PreOrder(pRoot->pLeft);
PreOrder(pRoot->pRight);
return;
}
/*
* 函数名称:PreOrderLoop
*
* 函数功能:前序遍历(非递归)
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void PreOrderLoop(BTNode * pRoot)
{
Stack stack;
BTNode * pCur = pRoot;
BTNode * pTop = NULL;
if (NULL == pRoot)
{
printf("\n");
return;
}
else
{
;
}
StackInit(&stack);
while (NULL != pCur || !StackIsEmpty(&stack))
{
while (NULL != pCur)
{
printf("%c ", pCur->data);
StackPush(&stack, pCur);
pCur = pCur->pLeft;
}
pTop = StackTop(&stack);
StackPop(&stack);
pCur = pTop->pRight;
}
StackDestory(&stack);
return;
}
/*
* 函数名称:InOrder
*
* 函数功能:中序遍历
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void InOrder(BTNode * pRoot)
{
if (NULL == pRoot)
{
return;
}
else
{
;
}
InOrder(pRoot->pLeft);
printf("%c ", pRoot->data);
InOrder(pRoot->pRight);
return;
}
/*
* 函数名称:InOrderLoop
*
* 函数功能:中序遍历(非递归)
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void InOrderLoop(BTNode * pRoot)
{
Stack stack;
BTNode * pCur = pRoot;
BTNode * pTop = NULL;
if (NULL == pRoot)
{
printf("\n");
return;
}
else
{
;
}
StackInit(&stack);
while (NULL != pCur || !StackIsEmpty(&stack))
{
while (NULL != pCur)
{
StackPush(&stack, pCur);
pCur = pCur->pLeft;
}
pTop = StackTop(&stack);
printf("%c ", pTop->data);
StackPop(&stack);
pCur = pTop->pRight;
}
StackDestory(&stack);
return;
}
/*
* 函数名称:PostOrder
*
* 函数功能:后序遍历
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void PostOrder(BTNode * pRoot)
{
if (NULL == pRoot)
{
return;
}
else
{
;
}
PostOrder(pRoot->pLeft);
PostOrder(pRoot->pRight);
printf("%c ", pRoot->data);
return;
}
/*
* 函数名称:PostOrderLoop
*
* 函数功能:后序遍历(非递归)
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void PostOrderLoop(BTNode * pRoot)
{
Stack stack;
BTNode * pCur = pRoot;
BTNode * pTop = NULL;
// 上一个被打印的结点
BTNode * pPrev = NULL;
if (NULL == pRoot)
{
printf("\n");
return;
}
else
{
;
}
StackInit(&stack);
while (NULL != pCur || !StackIsEmpty(&stack))
{
while (NULL != pCur)
{
StackPush(&stack, pCur);
pCur = pCur->pLeft;
}
pTop = StackTop(&stack);
// 右子树为空 或者 右子树已遍历过
if (NULL == pTop->pRight || pPrev == pTop->pRight)
{
printf("%c ", pTop->data);
StackPop(&stack);
pPrev = pTop;
continue;
}
else
{
pCur = pTop->pRight;
}
}
StackDestory(&stack);
return;
}
/*
* 函数名称:LevelOrder
*
* 函数功能:层序遍历
*
* 入口参数:pRoot
*
* 出口参数:void
*
* 返回类型:void
*/
void LevelOrder(BTNode * pRoot)
{
Queue queue;
BTNode * pFront = NULL;
if (NULL == pRoot)
{
printf("\n");
return;
}
else
{
;
}
QueueInit(&queue);
QueuePush(&queue, pRoot);
while (!QueueIsEmpty(&queue))
{
pFront = QueueFront(&queue);
printf("%c ", pFront->data);
QueuePop(&queue);
if (NULL != pFront->pLeft)
{
QueuePush(&queue, pFront->pLeft);
}
else
{
;
}
if (NULL != pFront->pRight)
{
QueuePush(&queue, pFront->pRight);
}
else
{
;
}
}
QueueDestory(&queue);
return;
}
/*
* 函数名称:TreeSize
*
* 函数功能:树的结点数(遍历)
*
* 入口参数:pRoot
*
* 出口参数:tree_count
*
* 返回类型:int
*/
//int tree_count = 0;
//
//int TreeSize(BTNode * pRoot)
//{
// if (NULL == pRoot)
// {
// return 0;
// }
// else
// {
// tree_count++;
// }
//
// TreeSize(pRoot->pLeft);
// TreeSize(pRoot->pRight);
//
// return tree_count;
//}
/*
* 函数名称:TreeSize
*
* 函数功能:树的结点数(递归)
*
* 入口参数:pRoot
*
* 出口参数:0 or TreeSize(pRoot->pLeft) + TreeSize(pRoot->pRight) + 1
*
* 返回类型:int
*/
int TreeSize(BTNode * pRoot)
{
if (NULL == pRoot)
{
return 0;
}
else
{
return TreeSize(pRoot->pLeft) + TreeSize(pRoot->pRight) + 1;
}
}
/*
* 函数名称:LeafSize
*
* 函数功能:叶子结点数(遍历)
*
* 入口参数:pRoot
*
* 出口参数:leaf_count
*
* 返回类型:int
*/
//int leaf_count = 0;
//
//int LeafSize(BTNode * pRoot)
//{
// if (NULL == pRoot)
// {
// return 0;
// }
// else if ((NULL == pRoot->pLeft) && (NULL == pRoot->pRight))
// {
// leaf_count++;
// }
// else
// {
// ;
// }
//
// LeafSize(pRoot->pLeft);
// LeafSize(pRoot->pRight);
//
// return leaf_count;
//}
/*
* 函数名称:LeafSize
*
* 函数功能:叶子结点数(递归)
*
* 入口参数:pRoot
*
* 出口参数:count
*
* 返回类型:int
*/
int LeafSize(BTNode * pRoot)
{
if (NULL == pRoot)
{
return 0;
}
else if ((NULL == pRoot->pLeft) && (NULL == pRoot->pRight))
{
return 1;
}
else
{
;
}
return LeafSize(pRoot->pLeft) + LeafSize(pRoot->pRight);
}
/*
* 函数名称:GetKSize
*
* 函数功能:求第k层的结点数
*
* 入口参数:pRoot, k
*
* 出口参数:0 or 1 or GetKSize(pRoot->pLeft, k-1) + GetKSize(pRoot->pRight, k-1)
*
* 返回类型:int
*/
int GetKSize(BTNode * pRoot, int k)
{
if (NULL == pRoot)
{
return 0;
}
if (NULL == pRoot && 1 == k)
{
return 0;
}
if (NULL != pRoot && 1 == k)
{
return 1;
}
return GetKSize(pRoot->pLeft, k - 1) + GetKSize(pRoot->pRight, k - 1);
}
/*
* 函数名称:GetHeight
*
* 函数功能:树的高度
*
* 入口参数:pRoot
*
* 出口参数:0 or MAX(leftH, rightH) + 1
*
* 返回类型:int
*/
int GetHeight(BTNode * pRoot)
{
int left_height = 0;
int right_height = 0;
if (NULL == pRoot)
{
return 0;
}
else
{
;
}
left_height = GetHeight(pRoot->pLeft);
right_height = GetHeight(pRoot->pRight);
return MAX(left_height, right_height) + 1;
}
/*
* 函数名称:Find
*
* 函数功能:查找第一次匹配的结点,若找到该结点则返回结点地址,反之则返回NULL
*
* 入口参数:pRoot, data
*
* 出口参数:NULL or pRoot or pFound or Find(pRoot->pRight, data)
*
* 返回类型:BTNode *
*/
BTNode * Find(BTNode * pRoot, DataType data)
{
BTNode *pFound = NULL;
if (NULL == pRoot)
{
return NULL;
}
if (data == pRoot->data)
{
return pRoot;
}
pFound = Find(pRoot->pLeft, data);
if (NULL != pFound)
{
return pFound;
}
return Find(pRoot->pRight, data);
//if (NULL != pRoot->pLeft)
//{
// return Find(pRoot->pLeft, data);
//}
//if (NULL != pRoot->pRight)
//{
// return Find(pRoot->pRight, data);
//}
//return NULL;
}
/*
* 函数名称:IsComplete
*
* 函数功能:判断当前二叉树是否是完全二叉树,假如是则返回1,反之则返回0
*
* 入口参数:pRoot
*
* 出口参数:0 or 1
*
* 返回类型:int
*/
int IsComplete(BTNode * pRoot)
{
Queue queue;
BTNode * pFront = NULL;
if (NULL == pRoot)
{
return 1;
}
QueueInit(&queue);
QueuePush(&queue, pRoot);
while (!QueueIsEmpty(&queue))
{
pFront = QueueFront(&queue);
if (NULL == pFront)
{
break;
}
else
{
;
}
QueuePop(&queue);
QueuePush(&queue, pFront->pLeft);
QueuePush(&queue, pFront->pRight);
}
while (!QueueIsEmpty(&queue))
{
pFront = QueueFront(&queue);
QueuePop(&queue);
if (NULL != pFront)
{
QueueDestory(&queue);
return 0;
}
else
{
;
}
}
QueueDestory(&queue);
return 1;
}
4、test.c
#define _CRT_SECURE_NO_WARNINGS 1
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:test.c
* 功能:测试二叉树的基本操作
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年6月13日22:30:02
*/
# include "tree.h"
# include "queue.h"
# include "stack.h"
/*
* 函数名称:main
*
* 函数功能:测试主程序
*
* 入口参数:void
*
* 出口参数:0
*
* 返回类型:int
*/
int main(void)
{
BTNode *pRoot = NULL;
BTNode *pFound = NULL;
int index = 0;
//不是完全二叉树
char array[] = { 'A', 'B', 'D',
'#', '#', '#',
'C', 'E', '#',
'#', 'F'};
//是完全二叉树
//char array[] = { 'A', 'B', 'D',
// '#', '#', 'G',
// '#', '#',
// 'C', 'E', '#',
// '#', 'F'};
pRoot = BuildTree(array, sizeof(array)/sizeof(char), &index);
printf("前序遍历二叉树(递归):\n");
PreOrder(pRoot);
printf("\n前序遍历二叉树(非递归):\n");
PreOrderLoop(pRoot);
printf("\n中序遍历二叉树(递归):\n");
InOrder(pRoot);
printf("\n中序遍历二叉树(非递归):\n");
InOrderLoop(pRoot);
printf("\n后序遍历二叉树(递归):\n");
PostOrder(pRoot);
printf("\n后序遍历二叉树(非递归):\n");
PostOrderLoop(pRoot);
printf("\n层序遍历二叉树:\n");
LevelOrder(pRoot);
printf("\n树的结点数为: %d\n", TreeSize(pRoot));
printf("叶子结点数为: %d\n", LeafSize(pRoot));
printf("第%d层结点数为: %d\n", 3, GetKSize(pRoot, 3));
printf("树的高度为: %d\n", GetHeight(pRoot));
pFound = Find(pRoot, 'A');
if (NULL != pFound)
{
printf("找到了 %c !\n", pFound->data);
}
else
{
printf("没找到!\n");
}
if (1 == IsComplete(pRoot))
{
printf("是完全二叉树!\n");
}
else
{
printf("不是完全二叉树!\n");
}
return 0;
}
输出结果