《数据结构(C语言版)》- 树和二叉树
来源:互联网 发布:淘宝卷和商品连在一起 编辑:程序博客网 时间:2024/05/23 01:19
本文将讨论非线性数据结构中的树型结构。树型结构中树和二叉树最常用,直观来说,树是以分支关系定义的层次结构,树结构在客观世界中广泛存在,如人类社会的族谱,最上面是族长,然后下面依次是族长的孩子,孙子等等。这就可以用树来更加形象的表示。树在计算机领域中也有十分广泛地应用,如在编译程序中,可用树来表示源程序的语法结构。
1. 树的定义
树的形状如下图:
树(Tree)是n(
有且仅有一个特定的称为根(Root)的结点,如图中的结点A就是这棵树的根节点;
当
n>1 时,其余结点可分为m(m>0 )个互不相交的有限集T1,T2,...,Tm ,其中每一个集合又可以作为一棵树,并称为根的子树(SubTree);
2. 树结构中的基本术语
下面将列出树结构中的一些基本术语:
树的结点所拥有的子树的个数称为结点的度(Degree)。如上图中,A的度为6,D的度为1,P的度为0;
度为0的结点称为叶子(Leaf)或终端结点。 如上图中,B,C,H,I,P,Q,K,L,M,N都是叶子结点;
树的度是树内各结点的度的最大值。如上图中,树的度为4;
结点的子树的根称为该结点的孩子(Child),该结点同样称为孩子的双亲(Parent)。如上图中,E为A的子树的根,则E为A的孩子,而A则是E的双亲;
同一个双亲的孩子之间互称兄弟(Sibling)。如上图中,B,C,D,E,F,G互为兄弟;
结点的祖先是从根到该结点所经过分支上的所有结点。反之,以某结点为根的子树中的任一结点都称为该结点的子孙。如上图中,P的祖先为A,E,J,E的子孙为I,J,P,Q;
结点的层次(Level)从根开始定义起,根为第一层,根的孩子为第二层,以此类推。
结点双亲都在同一层的结点互为堂兄弟。如上图中,H,I,J,K,L,M,N互为堂兄弟。
树中结点的最大层次称为树的深度(Depth)或高度。如上图中,树的深度为4;
如果将树中结点的各子树看成从左至右是有次序的(即不能互换),则称该树为有序树,否则称为无序树。如上图中,如果将A的以D为根的子树和以E为根的子树互换位置后和原先的树表示两颗树,则称该树为有序树,如果表示同一棵树,则称该树为无序树。在有序树中最左边的子树的根称为第一个孩子,最右边的称为最后一个孩子;
森林(Forest)是m(
m≥0 )棵互不相交的树的集合。
3. 二叉树的定义
二叉树(Binary Tree)是另一种树型结构,它的特点是每个结点至多只有两颗子树,也就是说,二叉树不存在度大于2的结点,并且二叉树的子树有左右之分,其次序不能任意颠倒。
一颗深度为
如果对满二叉树的结点进行连续编号,约定遍号从根节点起,自上而下,自左至右。其中,深度为
如下图,(a)和(b)分别为完成二叉树和满二叉树,而(c)和(d)为非完成二叉树:
抽象数据类型二叉树的定义如下:
4. 二叉树的性质
下面叙述二叉树的重要性质:
性质1 : 在二叉树的第
i 层上至多有2i−1 个结点(i≥1 )。性质2 : 深度为
k 的二叉树至多有2k−1 个结点(k≥1 )。性质3 :对任何一颗二叉树
T ,如果其叶子结点数为n0 ,度为2的结点数为n2 ,则n0=n2+1 。性质4 :具有
n 个结点的完全二叉树的深度为[log2n]+1 。性质5:如果对一颗有
n 个结点的完全二叉树的结点按层序编号,则对任一结点i(1≤i≤n) ,有:(1) 如果
i=1 ,则结点i 是二叉树的根,无双亲;如果i>1 ,则其双亲是结点[i/2] 。(2) 如果
2i>n ,则结点i 无左孩子(由于是完全二叉树,所以结点i 是叶子结点);否则其左孩子是结点2i 。(3) 如果
2i+1>n ,则结点i 无右孩子;否则其右孩子是结点2i+1 。
5. 二叉树的Java实现
下面是二叉树的Java实现:
二叉树结构类:
/** * Created by yuzhan on 2017/8/24. */public class TreeNode<T> { public T val; //结点值 public TreeNode<T> left; //左结点的值 public TreeNode<T> right; //右结点的值 public TreeNode(T data){ this.val = data; this.left = null; this.right = null; } public TreeNode(){ }}
二叉树方法接口
/** * 二叉树接口 * Created by yuzhan on 2017/8/24. */public interface BinaryTree<T> { /** * 构造空二叉树 */ TreeNode InitBiTree(); /** * 销毁二叉树 */ void DestroyBiTree(TreeNode tree); /** * 按Object[]构造二叉树 */ TreeNode CreateBiTree(Object[] array); /** * 将二叉树清为空树 */ void ClearBiTree(TreeNode tree); /** * 若二叉树存在,则返回TRUE,否则FALSE */ Boolean BiTreeEmpty(TreeNode tree); /** * 返回二叉树的根 * @return */ T Root(TreeNode tree); /** * 先序遍历 */ void preOrderByRecurse(TreeNode node); /** * 中序遍历 */ void InOrderByRecurse(TreeNode root); /** * 后序遍历 */ public void PostOrderByRecurse(TreeNode root);}
二叉树方法接口实现类
import java.util.ArrayList;import java.util.List;/** * 二叉树接口实现类 * Created by yuzhan on 2017/8/24. * */public class BinaryTreeImpl<T> implements BinaryTree<T>{ /** * 构造空二叉树T */ public TreeNode InitBiTree(){ return new TreeNode(); } /** * 销毁二叉树 */ public void DestroyBiTree(TreeNode tree){ if(tree != null){ tree.val = null; tree.left = null; tree.right = null; }else{ throw new IllegalArgumentException("二叉树为空"); } } /** * 按Object[]构造二叉树 */ public TreeNode CreateBiTree(Object[] array){ if(array == null || array.length == 0){ throw new IllegalArgumentException("输入不合法"); }else{ //将Object存入list中 List<TreeNode<T>> list = new ArrayList<>(); for(int i = 0;i < array.length;i++){ list.add(new TreeNode<T>((T) array[i])); } //为结点赋值(由于是完全二叉树构造方式,所以非叶子结点的数量为[n/2]) for(int j = 0;j < (list.size() /2);j++){ try { //为左子树赋值 2*j + 1 if((2*j + 1) < list.size()) list.get(j).left = list.get(2 * j + 1); else list.get(j).left = null; //为右子树赋值 2*j + 2 if((2*j + 2) < list.size()) list.get(j).right = list.get(2 * j + 2); else list.get(j).right = null; } catch (Exception e) { e.printStackTrace(); } } TreeNode tree = new TreeNode(); //为根结点赋值 tree.val = list.get(0).val; //为根结点的左子树赋值 if(list.get(0).left != null){ tree.left = list.get(0).left; }else{ tree.left = null; } //为根结点的右子树赋值 if(list.get(0).right != null){ tree.right = list.get(0).right; }else{ tree.right = null; } return tree; } } /** * 将二叉树清为空树 */ public void ClearBiTree(TreeNode tree){ if(tree.val != null){ tree.val = null; tree.right = null; tree.left = null; }else{ throw new IllegalArgumentException("二叉树为空"); } } /** * 若二叉树存在,则返回TRUE,否则FALSE */ public Boolean BiTreeEmpty(TreeNode tree){ if(tree.val != null){ return false; }else{ return true; } } /** * 返回二叉树的根 * @return */ public T Root(TreeNode tree){ if(tree.val != null){ return (T) tree.val; }else{ throw new IllegalArgumentException("二叉树为空"); } } /** * 先序遍历 */ public void preOrderByRecurse(TreeNode root) { if (root == null) { return; } System.out.print(root.val+" "); preOrderByRecurse(root.left); preOrderByRecurse(root.right); } /** * 中序遍历 */ public void InOrderByRecurse(TreeNode root) { if (root == null) { return; } InOrderByRecurse(root.left); System.out.print(root.val+" "); InOrderByRecurse(root.right); } /** * 后序遍历 */ public void PostOrderByRecurse(TreeNode root) { if (root == null) { return; } PostOrderByRecurse(root.left); PostOrderByRecurse(root.right); System.out.print(root.val+" "); }}
测试类
public static void main(String[] args) { BinaryTree<Integer> bt = new BinaryTreeImpl<>(); TreeNode tree; //tree = bt.InitBiTree(); // 初始化空二叉树 //bt.DestroyBiTree(tree); //销毁二叉树 Object[] array = {1,2,3,4,5,6,7,8,9,10}; tree = bt.CreateBiTree(array); //构造二叉树 //bt.ClearBiTree(); //清空二叉树 Boolean flag = bt.BiTreeEmpty(tree);//判断二叉树是否存在 Integer root = bt.Root(tree); //返回二叉树的根结点 bt.preOrderByRecurse(tree); //前序遍历 System.out.println(); bt.InOrderByRecurse(tree); //中序遍历 System.out.println(); bt.PostOrderByRecurse(tree); //后序遍历 }
- 《数据结构(C语言版)》- 树和二叉树
- 数据结构(C语言版)摘录--树和二叉树
- 数据结构 二叉树的实现 c语言版
- 数据结构C语言版之二叉树操作
- C语言版--二叉树
- C语言版--二叉树
- 数据结构 树 层次遍历二叉树 C语言版
- 数据结构 树 二叉树的建立及遍历 C语言版
- 数据结构与算法(C语言版)__二叉树
- 数据结构与算法(C语言版)__二叉查找树
- 数据结构实验:二叉树的遍历(C语言版)
- 二叉树(C语言版)
- 求二叉树的宽度C语言版
- 链式二叉树的遍历C语言版
- 问题 H: 数据结构(C语言版)算法6.1至算法6.4__二叉树遍历
- 数据结构 树 哈夫曼树及编码 C语言版
- 数据结构(C++)--二叉树
- 二叉树(数据结构 c++)
- iOS企业版(Enterprise) App发布,Safari打开URL显示无法连接"xxx"解决办法
- MySQL UNION与UNION ALL的区别
- Android中获取手机联系人的基本信息的实现
- 11. Container With Most Water
- 使用go语言net/http开发一个简单的get/post 接口
- 《数据结构(C语言版)》- 树和二叉树
- 以太坊研究课题
- hdu 1251 统计难题(字典树+空行输入)
- dfs序 题目小集
- 详解:路由器性能的各项指标
- Spring Bean生命周期详解
- 图-强连通模板
- 12. Integer to Roman
- 选择排序