问题:输入某二叉树的前序遍历和中序遍历的结果,重建出该二叉树,假设输入的前序遍历和终须遍历的结果都不含有重复数字。最后按层遍历输出二叉树结果。
public static void main(String[] args) {
// TODO 自动生成的方法存根
Character[] preOrder = new Character[] { 'a','b','d','g','c','e','f','h' };
Character[] inOrder = { 'd','g','b','a','e','c','h','f'};
Entry<Character> root = construct(preOrder, inOrder);
System.out.println(toString(root));
}
规定二叉树结点不含父节点字段。
private static class Entry<E> {
Entry<E> left, right;
E element;
Entry() {
}
Entry(E element) {
this.element = element;
}
}
解答:
前序遍历(根-左-右)
- preOrder(t){
- if(t非空){
- 访问t的根元素;
- preOrder(t的左子树);
- preOrder(t的右子树);
- }
- }
中序遍历(左-根-右)
- inOrder(t){
- if(t非空){
- inOrder(t的左子树);
- 访问t的根元素;
- inOrder(t的右子树);
- }
- }
程序使用泛型和迭代:
构建二叉树的函数分为两层,一层为public方法,可供外界程序调用;一层为private方法,实现构建功能:
public static <E> Entry<E> construct(E[] preOrder, E[] inOrder) {
if (preOrder == null || inOrder == null
|| preOrder.length != inOrder.length || inOrder.length <= 0)
return null;//检查输入的数组是否有效
return coreConstruct(preOrder, 0, preOrder.length - 1, inOrder, 0,
preOrder.length - 1);
}
private static <E> Entry<E> coreConstruct(E[] preOrder, int startPreOrder,
int endPreOrder, E[] inOrder, int startInOrder, int endInOrder) {
//越界检查,递归终止
if(startPreOrder>endPreOrder||startInOrder>endInOrder)
return null;
Entry<E> root = new Entry<E>(preOrder[startPreOrder]);// 前序遍历数组的最左边的元素是二叉树的根节点
// 在中序遍历数组中找到该根节点元素,它左边是左子树,右边是右子树
int rootInOrder = search(inOrder, root.element);//找到根结点索引
if (rootInOrder == -1) {//如果没找到该结点元素,说明给定的数组有问题
throw new IllegalArgumentException("输入数组无效");
}
int leftLength = rootInOrder - startInOrder;//左子树长度
int leftEndPreOrder = startPreOrder + leftLength;//前序遍历结果数组里当前根结点的左子树的最后一个元素的位置。
// 对其左子树和右子树迭代重建
if (leftLength > 0) {
// 如果左子树长度大于0,那就对左子树进行重建
root.left = coreConstruct(preOrder, startPreOrder + 1,
leftEndPreOrder, inOrder, startInOrder, rootInOrder - 1);
}
if (leftEndPreOrder < endPreOrder) {
//如果左子树最后一个元素的索引位置小于整个前序遍历数组最后一个索引位置,说明有右子树存在, 重建右子树
root.right = coreConstruct(preOrder, leftEndPreOrder + 1,
endPreOrder, inOrder, rootInOrder + 1, endInOrder);
}
return root;
}
/**
* @param array 待搜索的数组
* @param e 要被搜索的元素
* @return 被搜索的元素在数组中的位置。如果没有找到,就返回-1
*/
public static <E> int search(E[] array, E e) {
for (int i = 0; i < array.length; i++) {
if (array[i].equals(e))
return i;
}
return -1;
}
重建完毕后需要按层遍历输出
逐层遍历(宽度优先遍历)
- breadthFirst(t){
- //queue为二叉树(引用)的队列
- //t为二叉树(引用)
- if(t非空){
- queue.enqueue(t);
- while(queue不空){
- queue.dequeue(t); //从队列中移除根结点
- 访问被移除的根;
if(tree的左子树非空)
queue.enqueue(tree的左子树);
if(tree的右子树非空)
queue.enqueue(tree的右子树); - }
- }
- }
/**
* 宽度遍历,用一个链表保存结果
*
* @param root
* @return
*/
public static <E> List<E> breadthFirst(Entry<E> root) {
LinkedList<Entry<E>> list = new LinkedList<Entry<E>>();
ArrayList<E> result = new ArrayList<E>();
if (root != null)
list.addLast(root);
while (!list.isEmpty()) {
Entry<E> p = list.removeFirst();
result.add(p.element);
if (p.left != null) {
list.addLast(p.left);
}
if (p.right != null) {
list.addLast(p.right);
}
}
return result;
}
/**
* 使用宽度遍历逐层打印元素
*
* @param root
* 根节点
* @return
*/
public static <E> String toString(Entry<E> root) {
return breadthFirst(root).toString();
}
输出结果为[a, b, c, d, e, f, g, h]