bintree.h
#pragma once
#include <stdio.h>
typedef char BDataType;
typedef struct BinTreeNode
{
//struct BinTreeNode* _pParent; // 指向当前节点的双亲
struct BinTreeNode* _pLeft; // 指向当前节点左孩子
struct BinTreeNode* _pRight; // 指向当前节点右孩子
BDataType _data; // 当前节点值域
}BtRoot,*pBTNode;
//二叉树的创建
void bintree_create(pBTNode* tRoot,BDataType array[]);
//节点的创建
pBTNode bintreenode_create(BDataType data);
//遍历二叉树---前序(递归)
void PreOrder_D(pBTNode tRoot);
//遍历二叉树---前序(非递归)
void PreOrder_FD(pBTNode tRoot);
//遍历二叉树---中序(递归)
void MidOrder_D(pBTNode tRoot);
//遍历二叉树---中序(非递归)
void MidOrder_FD(pBTNode tRoot);
//遍历二叉树---后序(递归)
void PostOrder_D(pBTNode tRoot);
//遍历二叉树---后序(非递归)
void PostOrder_FD(pBTNode tRoot);
//层序遍历
void Levelorder(pBTNode tRoot);
//非递归遍历
//栈--前序遍历
//二叉树的复制
pBTNode Copy_bintree(pBTNode tRoot);
//镜像二叉树--非递归(层序)
void MirrorBinTree_FD(pBTNode* tRoot);
//镜像二叉树---递归(前序)
void MirrorBinTree_D(pBTNode* tRoot);
//交换节点
void swapNode(pBTNode* pLeft,pBTNode* pRight);
//二叉树节点个数
int BinTreeSize(pBTNode tRoot);
//二叉树的深度
int BinTreeDepth(pBTNode pRoot);
//求第k层的节点个数
int GetKLevelNode(pBTNode pRoot,int k);
// 二叉树的销毁
void DetroyBinTree(pBTNode* pRoot);
// 在二叉树中查找值为data的结点,找到返回该结点,否则返回空
pBTNode Find(pBTNode pRoot, BDataType data);
//找是否存在一个节点在二叉树中
int IsNodeInBinTree(pBTNode pRoot,pBTNode data);
//判断是否是完全二叉树
int IsCompleteBinTree(pBTNode pRoot);
1.二叉树的创建---采用递归的方法,创建根+左子树+右子树。
void bintree_create(pBTNode* tRoot,BDataType array[])
{
int index=0;
_bintree_create(tRoot,array,&index);
}
void _bintree_create(pBTNode* tRoot,BDataType array[],int* index)
{
assert(tRoot);
if('*' != array[*index] && '#'!=array[*index])
{
//根节点的创建
*tRoot=bintreenode_create(array[*index]);
//左子树的创建
++(*index);
_bintree_create(&(*tRoot)->_pLeft,array,index);
//右子树的创建
++(*index);
_bintree_create(&(*tRoot)->_pRight,array,index);
}
}.
2.二叉树节点的创建。
pBTNode bintreenode_create(BDataType data)
{
pBTNode pNewNode=NULL;
pNewNode=(pBTNode)malloc(sizeof(BtRoot));
if(NULL == pNewNode)
{
assert(pNewNode);
return NULL;
}
pNewNode->_data=data;
pNewNode->_pLeft=NULL;
pNewNode->_pRight=NULL;
return pNewNode;
}
3.二叉树的复制---同样是递归的方法
pBTNode Copy_bintree(pBTNode tRoot)
{
pBTNode pNewNode=NULL;
if(tRoot)
{
pNewNode=bintreenode_create(tRoot->_data);
Copy_bintree(tRoot->_pLeft);
Copy_bintree(tRoot->_pRight);
}
return pNewNode;
}
4.二叉树的遍历
(1)前序遍历---递归
void PreOrder_D(pBTNode tRoot)
{
if(tRoot)
{
printf("%c ",tRoot->_data);
PreOrder_D(tRoot->_pLeft);
PreOrder_D(tRoot->_pRight);
}
}
(2)前序遍历---非递归(两种方法)
void PreOrder_FD(pBTNode tRoot)
{
#if 0
pLstack s;
pBTNode pCur=NULL;
LstackInit(&s);
LstackPush(&s,tRoot);
if(NULL == tRoot)
return;
while (!LstackEmpty(s))
{
pCur=s->_data; //取栈顶
printf("%c ",pCur->_data);
LstackPop(&s); //出栈
if(pCur->_pRight)
LstackPush(&s,pCur->_pRight);
if(pCur->_pLeft)
LstackPush(&s,pCur->_pLeft);
}
#endif
pLstack s;
pBTNode pCur=NULL;
LstackInit(&s);
LstackPush(&s,tRoot);
if(NULL == tRoot)
return;
while (!LstackEmpty(s))
{
pCur=s->_data;
LstackPop(&s);
while (pCur)
{
printf("%c ",pCur->_data);
if(pCur->_pRight)
LstackPush(&s,pCur->_pRight);
pCur=pCur->_pLeft;
}
}
printf("\n");
}
(3)中序遍历---递归
void MidOrder_D(pBTNode tRoot)
{
if(tRoot)
{
MidOrder_D(tRoot->_pLeft);
printf("%c ",tRoot->_data);
MidOrder_D(tRoot->_pRight);
}
}
(4)中序遍历---非递归:需要用到栈(此处用的是链栈)先找到最左下角的节点,然后访问当前节点,出栈,访问当前节点的右节点。
void MidOrder_FD(pBTNode tRoot)
{
pLstack s;
pBTNode pCur=tRoot;
LstackInit(&s);
if(NULL == tRoot)
return;
while (pCur || (!LstackEmpty(s)))
{
while (pCur)
{
LstackPush(&s,pCur);
pCur=pCur->_pLeft;
}
pCur=s->_data;
printf("%c ",pCur->_data);
LstackPop(&s);
pCur=pCur->_pRight;
}
printf("\n");
}
(5)后序遍历---递归
void PostOrder_D(pBTNode tRoot)
{
if(tRoot)
{
PostOrder_D(tRoot->_pLeft);
PostOrder_D(tRoot->_pRight);
printf("%c ",tRoot->_data);
}
}
(6)后序遍历---非递归:需用到链栈,先找到最左下角的节点,并访问;然后判断,如果当前节点的右节点为空,或者右节点已经访问过了。就访问当前节点,否则向当前节点的右节点走。
void PostOrder_FD(pBTNode tRoot)
{
pLstack s;
pBTNode pCur=tRoot,pMark=NULL,pTop=NULL;
LstackInit(&s);
if(NULL == tRoot)
return;
while (pCur || (!LstackEmpty(s)))
{
while (pCur)
{
LstackPush(&s,pCur);
pCur=pCur->_pLeft;
}
pTop=s->_data; //取栈顶
if(NULL == pTop->_pRight || pTop->_pRight==pMark)
{
printf("%c ",pTop->_data);
pMark=pTop;
LstackPop(&s);
}
else
pCur=pTop->_pRight;
}
printf("\n");
}
(7)层序遍历:需用到队列(先进先出),根入队列,访问当前节点,然后左子树入队列,接着右子树入队列,循环。
void Levelorder(pBTNode tRoot)
{
Queue q;
pBTNode pCur=NULL;
if(NULL==tRoot)
return;
QueueInit(&q);
QPush(&q,tRoot);
while (!QueueEmpty(q))
{
pCur=Qfront(q);
QPop(&q);
printf("%c ",pCur->_data);
if(pCur->_pLeft)
QPush(&q,pCur->_pLeft);
if(pCur->_pRight)
QPush(&q,pCur->_pRight);
}
}
5.镜像二叉树
//镜像二叉树--非递归(层序)
void MirrorBinTree_FD(pBTNode* tRoot)
{
Queue q;
pBTNode pCur=NULL;
if(NULL==tRoot)
{
assert(tRoot);
return;
}
QueueInit(&q);
QPush(&q,*tRoot);
while (!QueueEmpty(q))
{
pCur=Qfront(q);
QPop(&q);
swapNode(&(pCur->_pLeft),&(pCur->_pRight));
if(pCur->_pLeft)
QPush(&q,pCur->_pLeft);
if(pCur->_pRight)
QPush(&q,pCur->_pRight);
}
}
//交换节点
void swapNode(pBTNode* pLeft,pBTNode* pRight)
{
pBTNode tmp=NULL;
tmp=*pLeft;
*pLeft=*pRight;
*pRight=tmp;
}
//镜像二叉树---递归(前序)
void MirrorBinTree_D(pBTNode* tRoot)
{
if(*tRoot)
{
swapNode(&((*tRoot)->_pLeft),&((*tRoot)->_pRight));
MirrorBinTree_FD(&((*tRoot)->_pLeft));
MirrorBinTree_FD(&((*tRoot)->_pRight));
}
}
6.//判断是否是完全二叉树:即如果是完全二叉树,只会出现一个“临界”节点(只有左节点,只有右节点或者无子节点),此时将标记flag置为1。当函数结束时,flag为1表示是完全二叉树,否则不是。
int IsCompleteBinTree(pBTNode pRoot)
{
Queue q;
pBTNode cur=NULL;
int flag=0;
if(NULL == pRoot)
return 0;
QueueInit(&q);
QPush(&q,pRoot);
while (!QueueEmpty(q))
{
cur=Qfront(q);
if(1==flag && (cur->_pLeft || cur->_pRight))
return 0;
if(cur->_pLeft && cur->_pRight) //左右子树均存在
{
QPush(&q,cur->_pLeft); //左子树入栈
QPush(&q,cur->_pRight); //右子树入栈
}
else if(cur->_pLeft) //仅左子树存在
{
QPush(&q,cur->_pLeft);
flag=1;
}
else if(cur->_pRight) //仅右子树存在
{
QPush(&q,cur->_pRight);
flag=1;
}
else //当前节点无子树
flag=1;
QPop(&q);
}
return 1;
}
7.其他基本操作
//二叉树节点个数
int BinTreeSize(pBTNode tRoot)
{
if(NULL == tRoot)
return 0;
return 1+BinTreeSize(tRoot->_pLeft)+BinTreeSize(tRoot->_pRight);
}
//二叉树的深度
int BinTreeDepth(pBTNode pRoot)
{
int Dleft=0,Dright=0;
if(NULL == pRoot)
return 0;
Dleft=BinTreeDepth(pRoot->_pLeft);
Dleft=BinTreeDepth(pRoot->_pRight);
return Dleft>Dright?(Dleft+1):(Dright+1);
}
//求第k层的节点个数
int GetKLevelNode(pBTNode pRoot,int k)
{
if(NULL == pRoot)
return 0;
if( 1== k)
return 1;
return GetKLevelNode(pRoot->_pLeft,k-1)+GetKLevelNode(pRoot->_pRight,k-1);
}
// 二叉树的销毁
void DetroyBinTree(pBTNode* pRoot)
{
if(NULL == (*pRoot))
return;
if((*pRoot)->_pLeft)
DetroyBinTree(&((*pRoot)->_pLeft));
if((*pRoot)->_pRight)
DetroyBinTree(&((*pRoot)->_pRight));
free(*pRoot);
}
// 在二叉树中查找值为data的结点,找到返回该结点,否则返回空
pBTNode Find(pBTNode pRoot, BDataType data)
{
pBTNode pCur=NULL;
Queue q;
QueueInit(&q);
if(NULL == pRoot)
return NULL;
pCur=pRoot;
QPush(&q,pCur);
while (!QueueEmpty(q))
{
pCur=Qfront(q);
if(data==pCur->_data)
return pCur;
if(pCur->_pLeft)
QPush(&q,pCur->_pLeft);
if(pCur->_pRight)
QPush(&q,pCur->_pRight);
QPop(&q);
}
printf("没找到\n");
return NULL;
}
//找是否存在一个节点在二叉树中
int IsNodeInBinTree(pBTNode pRoot,pBTNode pNode)
{
if(NULL== pRoot)
return 0;
if(pNode==pRoot)
return 1;
if(IsNodeInBinTree(pRoot->_pLeft,pNode))
return 1;
if(IsNodeInBinTree(pRoot->_pRight,pNode))
return 1;
return 0;
}
test.c
#include "bintree.h"
#include "Linkstack.h"
int main()
{
pBTNode bintree,pNewNode;
char array[]="ABC###DE##F**";
bintree_create(&bintree,array);
//前序遍历
printf("前序遍历\n");
PreOrder_D(bintree);
printf("\n");
PreOrder_FD(bintree);
printf("中序遍历\n");
MidOrder_D(bintree);
printf("\n");
MidOrder_FD(bintree);
printf("后序遍历\n");
PostOrder_D(bintree);
printf("\n");
PostOrder_FD(bintree);
//pNewNode=Copy_bintree(bintree);
//PreOrder_D(bintree);
//层序遍历
//Levelorder(bintree);
//镜像二叉树-递归
//MirrorBinTree_D(&bintree);
//镜像二叉树-递归
MirrorBinTree_FD(&bintree);
PreOrder_D(bintree);
//Levelorder(bintree);
printf("大小 = %d\n",BinTreeSize(bintree));
printf("深度 = %d\n",BinTreeDepth(bintree));
if(IsCompleteBinTree(bintree))
printf("是完全二叉树\n");
else
printf("不是完全二叉树\n");
//求第k层节点个数
printf("%d\n",GetKLevelNode(bintree,1));
pNewNode=Find(bintree,'F');
if(IsNodeInBinTree(bintree,pNewNode))
printf("找到了\n");
else
printf("没找到\n");
DetroyBinTree(&bintree);
return 0;
}