20172317 2018-2019-1 《程序设计与数据结构》第6周学习总结
教材学习内容总结
- 树: 一种非线性结构,其中元素被组织成一个层次结构;树由一个包含结点和边的集构成
- 元素存储于结点中,边将结点之间互相连接起来
- 根: 位于该树顶层的唯一结点;一棵树只能有一个根结点
- 位于树中较低层的结点是上一层结点的子结点(孩子);同一双亲的两个结点称为同胞结点(兄弟)
- 根结点是树中唯一没有双亲的结点
- 没有子结点的结点称为叶结点(叶子)
- 至少有一个子结点的非根结点称为一个内部结点
- 路径长度:从根结点到某一结点所必须越过的边数目
- 树的高度:从根结点到叶结点之间最远路径的长度
- 树的分类
- 树的度:树中任意结点可以具有的最大子结点数目
- 广义树:对结点所含有的子结点数目无限制的树
- n元树:每一结点限制为不超过n个子结点的树
- 树的平衡与否:若树的所有叶结点都位于同一层或彼此相差不超过一个层
- 含m个元素的平衡n元树具有的高度是logn(m)
- 完全树定义方式1:一个树,平衡,且底层所有叶子都位于树的左边
- 完全树定义方式2:完全二叉树在每个k层上都具有2^k个结点,最后一层除外,且在最后一层中的结点必须是最左边的结点
- 树实现策略:链式结构实现树和数组实现树
- 树的数组实现--计算策略(二叉树):对于存储在数组位置n处的元素而言,该元素的左子结点存储在(2n+1)处,右子结点存储在(2(n+1))处
- 此策略缺陷:若树非完全,则不包含元素的树位置也会被数组分配空间,浪费存储空间
- 树的数组实现--模拟连接策略(二叉树)
- 树的链表实现(二叉树):BinaryTreeNode对象包含一个元素(结点的元素),两个分别指向左子结点和右子结点的指针(如果没有子结点则为null,仅有一结点优先作为左结点处理)
- 树的遍历有四种基本方法(都是二叉树):前序遍历,中序遍历,后序遍历,层序遍历
- 前序遍历:从根结点开始访问每一结点及其子结点;
- 子结点优先遍历左子结点,如果正在遍历的结点有子结点则先遍历子结点(与其在同一层另一个同胞结点在遍历完子结点再遍历)
- 中序遍历:从根结点开始,访问结点的左子结点,然后是该结点,再然后是任何剩余结点;
- 递归式的遍历直到最远的子结点(叶结点),然后才开始用上述方法(访问左子结点,然后该结点,然后剩余结点)访问结点
- 后序遍历:从根结点开始,访问结点的子结点,然后是该结点
- 递归式的遍历直到最远的子结点(叶结点),然后才开始用上述方法(访问子结点,然后该结点)访问结点
- 层序遍历:从根结点开始,访问每一层的所有结点,一次一层
教材学习中的问题和解决过程
代码调试中的问题和解决过程
- 问题1:PP10.1:
removeRightSubtree
- 问题1解决方案:此方案由BinaryTreeNode类派生
移除右边的subtree,将此结点右边的子结点设为null,相应的右子结点的后代结点也会被移除
public void removeRightSubtree()
{
right = null;
}
- 问题2:PP10.1:
removeAllElements
- 问题2解决方案:此方案由BinaryTreeNode类派生
移除这个结点所有元素,即移除结点元素并移除后代结点
public void removeAllElements()
{
element = null;
right = null;
left = null;
}
- 问题3:PP10.3
- 问题3解决方案:判断是叶结点或是内部结点,需要判断该结点有无子结点,若没有,则为叶结点
public boolean isLeaf()
{
boolean a = false;
if (left == null && right == null)
{
a = true;
}
retrun a;
}
- 问题4:PP10.5
- 问题4解决方案:contains方法判定制定目标是否在该树中;基于find方法,find方法如果没有找到目标,会抛出异常,在contains方法中使用find方法,用try/catch捕获find方法的异常,并输出布尔值
public boolean contains(T targetElement)
{
boolean a = true;
try
{
find(targetElement);
}
catch (ElementNotFoundException e)
{
a = false;
}
return a;
}