- 实验内容
实验一:BinaryTree<T>二叉树类增加以下成员方法,public 权限
-
- BinaryTree<T> create(SeqList<T> inList, SeqList<T> postList); //以中根和后根遍历序列构造二叉树
- void leaf(); //输出叶子结点
- BinaryNode<T> parent(BinaryNode<T> p); //返回p结点的父母结点
实验二:实现以下对二叉树的操作,public static 修饰,要求一次遍历效率
-
- void property3(BinaryTree<T> bitree); //验证二叉树的性质3
- void swap(BinaryTree<T> bitree); //交换结点的左右子树,讨论3种遍历算法的可行性
- 实验方法及实现
根据实验内容和要求,将自己实现的程序代码写在此处,分析算法的时间复杂度。
实验一:BinaryNode.java
```java
public class BinaryNode<T> {
public T data;
public BinaryNode<T> left;
public BinaryNode<T> right;
public BinaryNode(T data) {
this.data = data;
this.left = null;
this.right = null;
}
}
```
SeqList.java
```java
public class SeqList<T> {
private Object[] data;
private int size;
public SeqList(int capacity) {
this.data = new Object[capacity];
this.size = 0;
}
public SeqList(T[] array) {
this.data = array;
this.size = array.length;
}
public int size() {
return this.size;
}
public T get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index out of range: " + index);
}
return (T) data[index];
}
public void set(int index, T value) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index out of range: " + index);
}
data[index] = value;
}
public void add(T value) {
if (size == data.length) {
throw new RuntimeException("List is full");
}
data[size++] = value;
}
}
```
BinaryTree.java
```java
public class BinaryTree<T> {
private BinaryNode<T> root;
public BinaryTree() {
this.root = null;
}
public BinaryTree(BinaryNode<T> root) {
this.root = root;
}
public BinaryNode<T> getRoot() {
return this.root;
}
public void setRoot(BinaryNode<T> root) {
this.root = root;
}
public BinaryTree<T> create(SeqList<T> inList, SeqList<T> postList) {
if (inList.size() != postList.size()) {
throw new IllegalArgumentException("Input lists have different sizes");
}
return new BinaryTree<>(createHelper(inList, 0, inList.size() - 1, postList, 0, postList.size() - 1));
}
private BinaryNode<T> createHelper(SeqList<T> inList, int inStart, int inEnd, SeqList<T> postList, int postStart, int postEnd) {
if (inStart > inEnd || postStart > postEnd) {
return null;
}
T rootData = postList.get(postEnd);
BinaryNode<T> root = new BinaryNode<>(rootData);
int rootIndex = inList.size() - 1;
for (int i = inStart; i <= inEnd; i++) {
if (inList.get(i).equals(rootData)) {
rootIndex = i;
break;
}
}
int leftSize = rootIndex - inStart;
root.left = createHelper(inList, inStart, rootIndex - 1, postList, postStart, postStart + leftSize - 1);
root.right = createHelper(inList, rootIndex + 1, inEnd, postList, postStart + leftSize, postEnd - 1);
return root;
}
public void leaf() {
leafHelper(root);
}
private void leafHelper(BinaryNode<T> node) {
if (node == null) {
return;
}
if (node.left == null && node.right == null) {
System.out.print(node.data + " ");
}
leafHelper(node.left);
leafHelper(node.right);
}
public BinaryNode<T> parent(BinaryNode<T> p) {
return parentHelper(root, p);
}
private BinaryNode<T> parentHelper(BinaryNode<T> node, BinaryNode<T> p) {
if (node == null) {
return null;
}
if (node.left == p || node.right == p) {
return node;
}
BinaryNode<T> leftResult = parentHelper(node.left, p);
if (leftResult != null) {
return leftResult;
}
return parentHelper(node.right, p);
}
}
```
TestBinaryTree.java
```java
public class TestBinaryTree {
public static void main(String[] args) {
// Create binary tree from inorder and postorder traversal sequences
SeqList<Integer> inList = new SeqList<>(new Integer[]{4, 2, 5, 1, 6, 3, 7});
SeqList<Integer> postList = new SeqList<>(new Integer[]{4, 5, 2, 6, 7, 3, 1});
BinaryTree<Integer> tree = new BinaryTree<>();
tree = tree.create(inList, postList);
System.out.print("Inorder traversal: ");
inorder(tree.getRoot());
System.out.println();
System.out.print("Postorder traversal: ");
postorder(tree.getRoot());
System.out.println();
// Print leaf nodes
System.out.print("Leaf nodes: ");
tree.leaf();
System.out.println();
// Find parent node
BinaryNode<Integer> node = tree.getRoot().left.right;
BinaryNode<Integer> parent = tree.parent(node);
System.out.println("Parent of " + node.data + " is " + parent.data);
}
private static void inorder(BinaryNode<Integer> node) {
if (node == null) {
return;
}
inorder(node.left);
System.out.print(node.data + " ");
inorder(node.right);
}
private static void postorder(BinaryNode<Integer> node) {
if (node == null) {
return;
}
postorder(node.left);
postorder(node.right);
System.out.print(node.data + " ");
}
}
```
① create(SeqList<T> inList, SeqList<T> postList) 方法的时间复杂度为 O(n^2),其中 n 为二叉树的结点数。
② leaf() 方法的时间复杂度为 O(n),其中 n 为二叉树的结点数。
③ parent(BinaryNode<T> p) 方法的时间复杂度为 O(n),其中 n 为二叉树的结点数。
实验二:
public class BinaryTree<T> {
private T data;
private BinaryTree<T> leftChild;
private BinaryTree<T> rightChild;
public BinaryTree(T data) {
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
public void setLeftChild(BinaryTree<T> leftChild) {
this.leftChild = leftChild;
}
public void setRightChild(BinaryTree<T> rightChild) {
this.rightChild = rightChild;
}
public void property3(BinaryTree<T> bitree) {
if (bitree == null) {
return;
}
if (bitree.leftChild != null && ((Comparable) bitree.leftChild.data).compareTo(bitree.data) > 0) {
throw new IllegalArgumentException("Binary tree does not satisfy property 3.");
}
if (bitree.rightChild != null && ((Comparable) bitree.rightChild.data).compareTo(bitree.data) < 0) {
throw new IllegalArgumentException("Binary tree does not satisfy property 3.");
}
property3(bitree.leftChild);
property3(bitree.rightChild);
}
public void swap(BinaryTree<T> bitree) {
if (bitree == null) {
return;
}
BinaryTree<T> temp = bitree.leftChild;
bitree.leftChild = bitree.rightChild;
bitree.rightChild = temp;
swap(bitree.leftChild);
swap(bitree.rightChild);
}
public static void main(String[] args) {
BinaryTree<Integer> root = new BinaryTree<>(4);
BinaryTree<Integer> node1 = new BinaryTree<>(2);
BinaryTree<Integer> node2 = new BinaryTree<>(6);
BinaryTree<Integer> node3 = new BinaryTree<>(1);
BinaryTree<Integer> node4 = new BinaryTree<>(3);
BinaryTree<Integer> node5 = new BinaryTree<>(5);
BinaryTree<Integer> node6 = new BinaryTree<>(7);
root.setLeftChild(node1);
root.setRightChild(node2);
node1.setLeftChild(node3);
node1.setRightChild(node4);
node2.setLeftChild(node5);
node2.setRightChild(node6);
// Test property3 method
try {
root.property3(root);
System.out.println("Binary tree satisfies property 3.");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
// Test swap method
root.swap(root);
System.out.println("In-order traversal after swapping:");
inOrderTraversal(root);
}
private static void inOrderTraversal(BinaryTree<Integer> bitree) {
if (bitree == null) {
return;
}
inOrderTraversal(bitree.leftChild);
System.out.print(bitree.data + " ");
inOrderTraversal(bitree.rightChild);
}
}
① 验证二叉树的性质3,即对于二叉树中的任意一个结点,其左子树中所有结点的值都小于该结点的值,其右子树中所有结点的值都大于该结点的值。可以通过一次中序遍历来实现,时间复杂度为 O(n),其中 n 为二叉树中结点的个数。
② 交换结点的左右子树,可以通过递归遍历实现,由于每个结点只会被访问一次,因此时间复杂度为 O(n),其中 n 为二叉树中结点的个数。无论是前序遍历、中序遍历还是后序遍历,都可以实现交换结点的左右子树。