树的基本操作
来源:互联网 发布:apple id被盗 mac被锁 编辑:程序博客网 时间:2024/06/06 03:43
树是一种来描述对象之间一对多关系的数据结构,可以是一对二,也可以是一对三,以此类推,但是二叉树应用广泛。
树的遍历
遍历一棵二叉树就是按某种次序系统地“访问”二叉树上的所有结点,并使每一个结点恰好被访问一次。所谓“访问”一个结点,是指对该结点的数据域进行某种处理,处理的内容依具体问题而定,通常比较简单。我们知道,遍历一个线性结构很容易,只须从开始结点出发顺序扫描每个结点即可。但是二叉树是一个非线性结构,每个结点可以有两个后继结点,因此需要寻找一种规律来系统地访问树中各结点。遍历运算的关键在于访问结点的“次序”,这种次序应保证二叉树上的每个结点均被访问一次且仅一次。
由定义可知,一棵二叉树由三部分组成:根、左子树和右子树。因此对于二叉树的遍历也可相应地分解成三项“子任务”:
①访问根结点;
②遍历左子树(即依次访问左子树上的全部结点);
③遍历右子树(即依次访问右子树上的全部结点)。
因为左、右子树都是二叉树(可以是空二叉树),对它们的遍历可以按上述方法继续分解,直到每棵子树均为空二叉树为止。由此可见,上述三项子任务的次序决定了遍历的次序。若以D、L、R分别表示这三项子任务,则共有6种可能的次序:DLR、LDR、LRD、DRL、RDL和RLD。通常限定“先左后右”,即子任务②在子任务③之前完成,这样就只剩下前三种次序,按这三种进行的遍历分别称为*先根遍历(或前序遍历)、中根(或中序)遍历、后根(或后序)遍历。三种遍历方法的定义如下。*
先根遍历 若需遍历的二叉树为空,执行空操作;否则,依次执行下列操作:
①访问根结点;
②先根遍历左子树;
③先根遍历右子树。
中根遍历 若需遍历的二叉树为空,执行空操作;否则,依次执行下列操作:
①中根遍历左子树;
②访问根结点;
③中根遍历右子树。
后根遍历 若需遍历的二叉树为空,执行空操作;否则,依次执行下列操作:
①后根遍历左子树;
②后根遍历右子树;
③访问根结点。
显然,上述三种遍历方法的区别在于执行子任务“访问根结点”的“时机”不同;若最先(最后、在中间)执行此子任务,则为先根(后根、中根)遍历。
按某种遍历方法遍历一棵二叉树,将得到该二叉树上所有结点的访问序列. 除此之外树还可以进行层次遍历按层数从小到大,每层从左到右的顺序进行遍历,这种遍历叫做广义遍历,用队列实现。
树的顺序遍历
#include<cstdio>#include<iostream>using namespace std;typedef struct A{ char c; A* l_child; A* r_child;} tree;tree* createtree()//建树{ tree* T; T=new tree; char c; c=getchar(); if(c=='#') { T=NULL; } else { T->c=c; T->l_child=createtree(); T->r_child=createtree(); } return T;}void preorder(tree* T)//前序遍历{ if(T!=NULL) { printf("%c",T->c); preorder(T->l_child); preorder(T->r_child); }}void inorder(tree* T)//中序遍历{ if(T!=NULL) { inorder(T->l_child); printf("%c",T->c); inorder(T->r_child); }}void postorder(tree* T)//后序遍历{ if(T!=NULL) { postorder(T->l_child); postorder(T->r_child); printf("%c",T->c); }}int main(){ tree* T; T=createtree(); preorder(T); printf("\n"); inorder(T); printf("\n"); postorder(T); printf("\n"); return 0;}
广义表建树
void genlist_createtree (){ queue<tree*> s tree* T; //分别代表根节点,和当前所要处理的节点。 char c; int k; //用来存储下一步该存储那个节点的状态,1代表左孩子,2代表右孩子 T->l_child=NULL; T->r_child=NULL; c=getchar(); if(c!='#') { T->c=c; } while(c=getchar()) { switch(c) { case '(': s.push(T) k=1; break; case ',': k=2; break; case ')': s.pop(); break; default: T=new tree; T->c=c; T->l_child=NULL; T->r_child=NULL; if(k==1) s.front()->l_child=T; else s.front()->r_child=T; } }}
以上是广义表建树过程实际上是相当于按照次序找根节点。本质上和顺序建树的思想一样都是将树将根,左孩子,右孩子按一定的顺序进行创建,只是一种用递归实现,一种用队列实现。
交换树的左右孩子
void exchangechild(tree* T){ if(T) { tree* temp; if(T->l_child||T->r_child) { temp=T->l_child; T->l_child=T->r_child; T->r_child=temp; exchangechild(T->l_child); exchangechild(T->r_child); } }}
求树的深度
int treedepth(tree* T){ int ldepth; int rdepth; if(T==NULL)//找到叶子的子节点 return 0; ldepth=treedepth(T->l_child);//每次找子节点的高度 rdepth=treedepth(T->r_child); return (ldepth>rdepth)?(ldepth+1):(rdepth+1);//返回左右节点深度最大的。}
求叶子节点的个数
int leaf(tree* T){ if(T==NULL)//如果树空返回 0 return 0; if(T->l_child==NULL&&T->r_child==NULL) return 1; return leaf(T->l_child)+leaf(T->r_child);}
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 平衡树的基本操作
- Tomcat原理详解和各种集群的实现
- 博为峰Java技术文章 ——JavaSE 如何使用颜色选取器JColorChooser
- C/C++笔试题(一)
- mysql 分页排序
- 结业小项目
- 树的基本操作
- Dertermining IP information for eth0 .... failed
- 基于ARM9的伪指令汇总
- 平时学习用到的一些资料的记录
- [编程题] 奇怪的表达式求值
- hdu 4826 Labyrinth
- Message类源码
- POJ 3067 Japan (树状数组求逆序数---经典)
- lintcode/leetcode由易至难第1题:返回第n个斐波那契数