二叉树基本操作之递归和非递归遍历、分支节点数详解
二叉树的定义
二叉树是由n(n>=0)个结点的有限集合构成,此集合或者为空集,或者由一个根结点及两棵互不相交的左右子树组成,并且左右子树都是二叉树.
递归定义:叉树可以是空集合,根可以有空的左子树或空的右子树。二叉树不是树的特殊情况,它们是两个概念。
typedef char ElemType; typedef struct BiTNode{ ElemType data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree;
二叉树的遍历
原表达式:a+b*(c-d)-e/f
先序遍历:-+a*b-cd/ef
中序遍历:a+b*c-d-e/f
后序遍历:abcd-*+ef/-
先序递归遍历过程
即先序遍历完成
void PreOrderTraverse(BiTree BT) { if(BT) { if(!(BT->data)) return; printf("%c",BT->data); PreOrderTraverse(BT->lchild); PreOrderTraverse(BT->rchild); } }
中序遍历和后序遍历同上
层次非递归遍历
该树的层次递归遍历为:ABCDEGF
运用队列来存储树的结点首先A入队,输出A结点,然后队首结点A出队,将A的孩子结点B,C分别入队。访问队首结点B,输出并出队,将B的孩子结点D,E入队。访问队首结点C,输出并出队,C结点只有右孩子,将C的右孩子结点G入队。访问队首结点D,输出并出队,D没有孩子结点,不入队。访问队首结点E,输出并出队,将E的孩子结点F入队。访问队首结点G,输出并出队,G没有孩子结点,不入队。访问队首结点F,输出并出队,F没有孩子结点,不入队。此时队列为空,结束遍历。
void leverTraverse(BiTree BT) { Squeue Q; BiTree pt=BT; InitQueue(&Q); EnQueue(&Q,pt); while(!EmptyQueue(Q)) { Dequeue(&Q,&pt); printf("%c",pt->data); if(pt->lchild) EnQueue(&Q,pt->lchild); if(pt->rchild) EnQueue(&Q,pt->rchild); } }
完整代码:
// erchashu.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "stdlib.h" #include "string.h" #define MAXSIZE 50 int max=0; typedef char ElemType; typedef struct BiTNode{ ElemType data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; typedef struct SQueue{ BiTree *base; int front; int rear; }Squeue; void InitBiTree(BiTree *BT) { *BT=NULL; } void PreCreatBiTree(BiTree *BT) { ElemType ch; printf("输入数据:\n"); getchar(); ch=getchar(); if(ch=='#') *BT=NULL; else { *BT=(BiTree)malloc(sizeof(BiTNode)); (*BT)->data=ch; PreCreatBiTree(&(*BT)->lchild); PreCreatBiTree(&(*BT)->rchild); } } void PreOrderTraverse(BiTree BT) { if(BT) { if(!(BT->data)) return; printf("%c",BT->data); PreOrderTraverse(BT->lchild); PreOrderTraverse(BT->rchild); } } void InOrderTraverse(BiTree BT) { if(BT) { if(!(BT->data)) return; InOrderTraverse(BT->lchild); printf("%c",BT->data); InOrderTraverse(BT->rchild); } } void PostOrderTraverse(BiTree BT) { if(BT) { if(!(BT->data)) return; PostOrderTraverse(BT->lchild); PostOrderTraverse(BT->rchild); printf("%c",BT->data); } } void InitQueue(Squeue *Q) { (*Q).base=(BiTree *)malloc(sizeof(BiTNode)*MAXSIZE); (*Q).front=(*Q).rear=0; } void EnQueue(Squeue *Q,BiTree BT) { (*Q).base[(*Q).rear++]=BT; } int EmptyQueue(Squeue Q) { if(Q.front==Q.rear) return 1; return 0; } void Dequeue(Squeue *Q,BiTree *pt) { if((*Q).front==(*Q).rear) return; *pt=(*Q).base[(*Q).front]; (*Q).front=((*Q).front +1) % MAXSIZE; } void leverTraverse(BiTree BT) { Squeue Q; BiTree pt=BT; InitQueue(&Q); EnQueue(&Q,pt); while(!EmptyQueue(Q)) { Dequeue(&Q,&pt); printf("%c",pt->data); if(pt->lchild) EnQueue(&Q,pt->lchild); if(pt->rchild) EnQueue(&Q,pt->rchild); } } void NRPreOrderTraverse(BiTree BT) { BiTree pt=BT,stack[MAXSIZE]; int top=0; while(pt || top) { if(pt) { printf("%c",pt->data); stack[top++]=pt; pt=pt->lchild; } else { pt=stack[--top]; pt=pt->rchild; } } } int BiTreedepth(BiTree BT,int depth) { if(BT) { if(BT->lchild) BiTreedepth(BT->lchild,depth+1); if(BT->rchild) BiTreedepth(BT->rchild,depth+1); } if(depth>max) max=depth; return depth; } int LeafNumber(BiTree BT) { if(!BT) return 0; else { if((!BT->lchild) && (!BT->rchild)) return 1; else return LeafNumber(BT->lchild)+LeafNumber(BT->rchild); } } int singleBiTree(BiTree BT) { if(!BT) return 0; else { if(BT->lchild && !BT->rchild) return singleBiTree(BT->lchild)+1; else { if(!BT->lchild && BT->rchild) return singleBiTree(BT->lchild)+1; else return singleBiTree(BT->lchild)+singleBiTree(BT->rchild); } } } int doubleBiTree(BiTree BT) { int book=0; if(!BT) return 0; if(BT->lchild && BT->rchild) book=1; return book+doubleBiTree(BT->lchild)+doubleBiTree(BT->rchild); } void revoluteBiTree(BiTree *BT) { BiTree T; if(!(*BT)->lchild && !(*BT)->rchild) return; else { T=(*BT)->lchild; (*BT)->lchild=(*BT)->rchild; (*BT)->rchild=T; } if((*BT)->lchild) { revoluteBiTree(&(*BT)->lchild); } if((*BT)->rchild) { revoluteBiTree(&(*BT)->rchild); } } int main(int argc, char* argv[]) { BiTree BT; int tmp; int flag=1,select; InitBiTree(&BT); while(flag) { printf("\n请选择:\n"); printf("0. 先序创建二叉树用#代表空结点\n"); printf("1. 先序遍历\n"); printf("2. 中序遍历\n"); printf("3. 后序遍历\n"); printf("4. 非递归层次遍历\n"); printf("5. 非递归先序遍历\n"); printf("6. 二叉树高度\n"); printf("7. 叶结点数目\n"); printf("8. 单分支结点数目\n"); printf("9. 双分支结点数目\n"); printf("10. 交换二叉树\n"); printf("11.退出程序\n"); printf("请输入要执行的操作:\n"); scanf("%d",&select); switch(select) { case 0: PreCreatBiTree(&BT); break; case 1: printf("\n先序遍历为:\n"); PreOrderTraverse(BT); break; case 2: printf("\n中序遍历为:\n"); InOrderTraverse(BT); break; case 3: printf("\n后序遍历为:\n"); PostOrderTraverse(BT); break; case 4: printf("\n层次非递归遍历为:\n"); leverTraverse(BT); break; case 5: printf("\n先序非递归遍历为:\n"); NRPreOrderTraverse(BT); break; case 6: printf("\n高度为: "); BiTreedepth(BT,1); printf("%d\n",max); break; case 7: printf("\n叶结点数目为: "); tmp=LeafNumber(BT); printf("%d\n",tmp); break; case 8: printf("\n单分支结点数目为: "); tmp=singleBiTree(BT); printf("%d\n",tmp); break; case 9: printf("\n双分支结点数目为: "); tmp=doubleBiTree(BT); printf("%d\n",tmp); break; case 10: printf("\n已交换二叉树\n"); revoluteBiTree(&BT); break; default: flag=0; printf("Press any key to exit!\n"); break; } } printf("\n"); return 0; }
到此这篇关于二叉树基本操作之递归和非递归遍历、分支节点数详解的文章就介绍到这了,更多相关二叉树基本操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
详解使用IntelliJ IDEA新建Java Web后端resfulAPI模板
这篇文章主要介绍了详解使用IntelliJ IDEA新建Java Web后端resfulAPI模板,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-08-08java实现监控rtsp流转flv方法实例(前端播放,前后端代码都有)
这篇文章主要给大家介绍了关于java实现监控rtsp流转flv的相关资料,文中介绍的是前端播放,前后端代码都有,文中通过实例代码介绍的非常详细,需要的朋友可以参考下2023-06-06
最新评论