20202314 实验八 《数据结构与面向对象程序设计》实验报告
# 20202314 2021-2022-1 《数据结构与面向对象程序设计》实验八报告
课程:《程序设计与数据结构》
班级: 2023
姓名: 王鑫垚
学号:20202314
实验教师:王志强
实验日期:2021年11月18日
必修/选修: 必修
一、实验内容
1.参考教材PP16.1,完成链树LinkedBinaryTree的实现(getRight,contains,toString,preorder,postorder)
用JUnit或自己编写驱动类对自己实现的LinkedBinaryTree进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
2.基于LinkedBinaryTree,实现基于(中序,先序)序列构造唯一一棵二㕚树的功能,比如给出中序HDIBEMJNAFCKGL和后序ABDHIEJMNCFGKL,构造出附图中的树
用JUnit或自己编写驱动类对自己实现的功能进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
3.自己设计并实现一颗决策树
提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
4.输入中缀表达式,使用树将中缀表达式转换为后缀表达式,并输出后缀表达式和计算结果(如果没有用树,正常评分。如果用到了树,即使有小的问题,也酌情给满分)
提交测试代码运行截图,要全屏,包含自己的学号信息
二、实验过程及结果
1.参考教材PP16.1,完成链树LinkedBinaryTree的实现(getRight,contains,toString,preorder,postorder)
用JUnit或自己编写驱动类对自己实现的LinkedBinaryTree进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
二叉树节点代码
二叉树代码
测试结果
import junit.framework.TestCase; import org.junit.Test; public class LinkedBinaryTreeTest extends TestCase { LinkedBinaryTree tree11=new LinkedBinaryTree(1,null,null); LinkedBinaryTree tree10=new LinkedBinaryTree(2,tree11,null); LinkedBinaryTree tree9=new LinkedBinaryTree(14,null,null); LinkedBinaryTree tree8=new LinkedBinaryTree(8,tree10,tree9); LinkedBinaryTree tree7=new LinkedBinaryTree(19,null,null); LinkedBinaryTree tree6=new LinkedBinaryTree(16,tree8,tree7); LinkedBinaryTree tree4=new LinkedBinaryTree(33,null,null); LinkedBinaryTree tree3=new LinkedBinaryTree(36,tree4,null); LinkedBinaryTree tree2=new LinkedBinaryTree(41,tree3,null); LinkedBinaryTree tree1=new LinkedBinaryTree(39,null,tree2); LinkedBinaryTree tree5=new LinkedBinaryTree(30,tree6,tree1); @Test public void testgetright(){ assertEquals(""+41,""+tree1.getRight()); } @Test public void testroot(){ assertEquals(33+"",""+tree4.root); } @Test public void testleft(){ assertEquals(""+tree6,""+tree5.getLeft()); } @Test public void testtoString(){ assertEquals(""+39,""+tree1); } @Test public void testcontains(){ assertEquals(true,tree5.contains(30)); } @Test public void testsize(){ assertEquals(""+2,""+tree10.size()); } @Test public void testisEmpty(){ assertEquals(""+false,""+tree7.isEmpty()); } }
测试用代码
2.基于LinkedBinaryTree,实现基于(中序,先序)序列构造唯一一棵二㕚树的功能,比如给出中序HDIBEMJNAFCKGL和后序ABDHIEJMNCFGKL,构造出附图中的树
用JUnit或自己编写驱动类对自己实现的功能进行测试,提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
测试结果截图↑
1 import junit.framework.TestCase; 2 import org.junit.Test; 3 4 public class Tree2Test extends TestCase { 5 LinkedBinaryTree2 tree2=new LinkedBinaryTree2(); 6 BinaryTreeNode tree; 7 @Test 8 public void testTest2(){ 9 char[] midorder={'H','D','I','B','E','M','J','N','A','F','C','K','G','L'};/*HDIBEMJNAFCKGL*/ 10 char[] aftorder={'A','B','D','H','I','E','J','M','N','C','F','G','K','L'};/*ABDHIEJMNCFGKL*/ 11 tree=tree2.construct(aftorder,midorder); 12 String a =new String("H I D M N J E B F K L G C A "); 13 assertEquals(""+a,""+tree2.poseOrder(tree)); 14 } 15 16 }
测试用代码↑
1 import java.util.ArrayList; 2 import java.util.Arrays; 3 4 public class LinkedBinaryTree2<T> implements BinaryTree<T> { 5 protected BinaryTreeNode<T> root; 6 7 public LinkedBinaryTree2() { 8 root = null; 9 } 10 11 public LinkedBinaryTree2(T element) { 12 root = new BinaryTreeNode<T>(element); 13 } 14 15 public LinkedBinaryTree2(T element, LinkedBinaryTree2<T> left, LinkedBinaryTree2<T> right) { 16 root = new BinaryTreeNode<T>(element); 17 root.setLeft(left.root); 18 root.setRight(right.root); 19 } 20 21 public T getRootElement() throws EmptyCollectionException { 22 if (root == null) 23 throw new EmptyCollectionException("Get root operation " 24 + "failed. The tree is empty."); 25 26 return root.getElement(); 27 } 28 29 public LinkedBinaryTree2<T> getLeft() throws EmptyCollectionException { 30 if (root == null) 31 throw new EmptyCollectionException("Get left operation " 32 + "failed. The tree is empty."); 33 34 LinkedBinaryTree2<T> result = new LinkedBinaryTree2<T>(); 35 result.root = root.getLeft(); 36 37 return result; 38 } 39 40 public T find(T target) throws ElementNotFoundException { 41 BinaryTreeNode<T> node = null; 42 43 if (root != null) 44 node = root.find(target); 45 46 if (node == null) 47 throw new ElementNotFoundException("Find operation failed. " 48 + "No such element in tree."); 49 50 return node.getElement(); 51 } 52 53 //返回大小 54 public int size() { 55 int result = 0; 56 57 if (root != null) 58 result = root.count(); 59 60 return result; 61 } 62 63 public LinkedBinaryTree2<T> getRight() throws EmptyCollectionException { 64 if (root == null) 65 throw new EmptyCollectionException("Get right operation " 66 + "failed. The tree is empty."); 67 68 LinkedBinaryTree2<T> result = new LinkedBinaryTree2<T>(); 69 result.root = root.getRight(); 70 71 return result; 72 } 73 74 public boolean contains(T target) { 75 if (root.find(target) == null) { 76 return false; 77 } else { 78 return true; 79 } 80 } 81 82 public boolean isEmpty() { 83 if (root == null) { 84 return true; 85 } else { 86 return false; 87 } 88 } 89 90 //先序 91 public ArrayList<T> preorder() { 92 ArrayList<T> iter = new ArrayList<T>(); 93 94 if (root != null) 95 root.preorder(iter); 96 97 return iter; 98 } 99 100 //中序 101 public ArrayList<T> inorder() { 102 ArrayList<T> iter = new ArrayList<T>(); 103 104 if (root != null) 105 root.inorder(iter); 106 107 return iter; 108 } 109 110 //后序 111 public ArrayList<T> postorder() { 112 ArrayList<T> iter = new ArrayList<T>(); 113 114 if (root != null) 115 root.postorder(iter); 116 117 return iter; 118 } 119 120 //层序 121 public ArrayList<T> levelorder() throws EmptyCollectionException { 122 LinkedQueue<BinaryTreeNode<T>> queue = new LinkedQueue<BinaryTreeNode<T>>(); 123 ArrayList<T> iter = new ArrayList<T>(); 124 125 if (root != null) { 126 queue.enqueue(root); 127 while (!queue.isEmpty()) { 128 BinaryTreeNode<T> current = queue.dequeue(); 129 130 iter.add(current.getElement()); 131 132 if (current.getLeft() != null) 133 queue.enqueue(current.getLeft()); 134 if (current.getRight() != null) 135 queue.enqueue(current.getRight()); 136 } 137 } 138 return iter; 139 } 140 141 public String toString() { 142 return super.toString(); 143 } 144 145 public BinaryTreeNode construct(char[] pre, char[] in){ 146 if (pre.length == 0 || in.length == 0) { 147 return null; 148 } 149 BinaryTreeNode<Character> tree = new BinaryTreeNode<Character>(pre[0]); 150 int index = search(0, in.length, in, tree.getElement()); 151 tree.setLeft(construct(Arrays.copyOfRange(pre, 1, index + 1), Arrays.copyOfRange(in, 0, index))); 152 tree.setRight(construct(Arrays.copyOfRange(pre, index + 1, pre.length), 153 Arrays.copyOfRange(in, index + 1, in.length))); 154 return tree; 155 } 156 157 public int search(int start, int end, char[] inOrders, char data) { 158 for (int i = start; i < end; i++) { 159 if (data == inOrders[i]) { 160 return i; 161 } 162 } 163 return -1; 164 } 165 166 String poseOrder = ""; 167 public String poseOrder(BinaryTreeNode tree) { 168 BinaryTreeNode<T> leftTree = tree.left; 169 if(leftTree != null){ 170 poseOrder(leftTree); 171 } 172 BinaryTreeNode<T> rightTree = tree.right; 173 if(rightTree != null){ 174 poseOrder(rightTree); 175 } 176 poseOrder = poseOrder + tree.print() + " "; 177 return poseOrder; 178 } 179 }
修改后的二叉树类的代码↑
3.自己设计并实现一颗决策树
提交测试代码运行截图,要全屏,包含自己的学号信息
课下把代码推送到代码托管平台
以上为一种结果↑
另一种结果↑
4.输入中缀表达式,使用树将中缀表达式转换为后缀表达式,并输出后缀表达式和计算结果(如果没有用树,正常评分。如果用到了树,即使有小的问题,也酌情给满分)
提交测试代码运行截图,要全屏,包含自己的学号信息
测试结果截图↑
1 import junit.framework.TestCase; 2 3 import java.util.Scanner; 4 5 public class NameTest extends TestCase { 6 public static void main(String[] args) { 7 Scanner scan = new Scanner(System.in); 8 String jug="Y"; 9 do { 10 System.out.println("请输入您的中缀表达式,数字、字符空格隔开"); 11 String a = scan.nextLine(); 12 String rst = Name.transform(a); 13 System.out.println("后缀表达式为 " + rst); 14 System.out.println("结果是 " + Calculate.Calculate(rst)); 15 System.out.println("再来一次? Y/N"); 16 jug = scan.nextLine(); 17 if (jug.equals("N")) 18 break; 19 }while (jug.equals("Y")); 20 21 22 } 23 }
测试用代码
三. 实验过程中遇到的问题和解决过程
- 问题1:Junit测试报错
- 问题1解决方案:
老问题,因为在LinkedBinaryTree中的节点的Element选择了自定义的变量类型,导致Test中的assertEquals()方法无法正常的将两个类型的数据进行比较,仍然是通过(“”+变量)的方式来讲两个类型的数据都统一转换为String类型数据进行比较
- 问题2:实验过程中树的遍历不能正常运行
- 问题2解决方案:
开始的时候我自己写的遍历代码是通过假设原本是一棵完全二叉树且是满二叉树的情况来遍历所有的节点,来实现遍历。但是发现自己的遍历总是在根节点的左孩子和右孩子处戛然而止,于是我查阅了网上的二叉树遍历代码等等,发现自己的遍历原来是假遍历,虽然能够统计数据,但是没能够正确的移步到下一位。
## 其他(感悟、思考等)
虽然一个程序,一个类可能浩浩汤汤一百多行代码,但是其实最底层的逻辑搞通,积少成多其实一百多行的代码也并没有几个功能。保持逻辑正确非常关键。
## 参考资料
- [《Java程序设计与数据结构教程(第二版)》](https://book.douban.com/subject/26851579/)
- [《Java程序设计与数据结构教程(第二版)》学习指导](http://www.cnblogs.com/rocedu/p/5182332.html)
- ...