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; }