PAT-Java-Is It a Complete AVL Tree (30)

Is It a Complete AVL Tree

题目阐述

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.
这里写图片描述
Now given a sequence of insertions, you are supposed to output the level-order traversal sequence of the resulting AVL tree, and to tell if it is a complete binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<= 20). Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, insert the keys one by one into an initially empty AVL tree. Then first print in a line the level-order traversal sequence of the resulting AVL tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line. Then in the next line, print “YES” if the tree is complete, or “NO” if not.

Sample Input 1:
5
88 70 61 63 65
Sample Output 1:
70 63 88 61 65
YES
Sample Input 2:
8
88 70 61 96 120 90 65 68
Sample Output 2:
88 65 96 61 70 90 120 68
NO


题目分析

三小时里我留了一个小时40分钟来做这道题,没做出来。对AVL树只是知道它的性质,却从未亲自实现里面旋转等操作。参考了柳婼这篇博客柳婼 の blog里的解法,换成java自己实现了一遍,一次就全通过。

代码实现


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;

class Read {
	static BufferedReader br;
	static StringTokenizer st;
	static void init(InputStream in) {
		br = new BufferedReader(new InputStreamReader(in));
		st = new StringTokenizer("");
	}
	static String next() throws IOException {
		while (!st.hasMoreTokens()) {
			st = new StringTokenizer(br.readLine());
		}
		return st.nextToken();
	}
	static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}
}

public class Main {
	public static void main(String[] args) throws IOException {
		Read.init(System.in);
		int n = Read.nextInt();
		Node head = null;
		for (int i=0; i<n; i++) {
			int temp = Read.nextInt();
			head = insert(head, temp);
		}
		
		Queue<Node> q = new LinkedList<>();
		q.add(head);
		boolean isComplete = true, after = false;
		List<Integer> list = new ArrayList<>();
		while (!q.isEmpty()) {
			Node temp = q.poll();
			list.add(temp.val);
			if (temp.left != null) {
				q.add(temp.left);
				if (after) isComplete = false;
			} else {
				after = true;
			}
			if (temp.right != null) {
				q.add(temp.right);
				if (after) isComplete = false;
			} else {
				after = true;
			}
		}
		for (int i=0; i<list.size(); i++) 
			if (i != list.size()-1) System.out.print(list.get(i) + " ");
			else System.out.print(list.get(i) + "\n");
		if (isComplete) System.out.print("YES");
		else System.out.print("NO");
		
		
	}
	private static Node insert(Node tree, int val) {
		if (tree == null) {
			tree = new Node(val);
			return tree;
		}
		if (val < tree.val) {
			tree.left = insert(tree.left, val);
	        int l = getHeight(tree.left);
	        int r = getHeight(tree.right);
	        if (l - r >= 2) {
	            if (val < tree.left.val)
	                tree = rightRotate(tree);
	            else
	                tree = leftRightRotate(tree);
	        }
		} else {
			tree.right = insert(tree.right, val);
			int l = getHeight(tree.left);
	        int r = getHeight(tree.right);
	        if (r - l >= 2) {
	            if (val < tree.right.val)
	                tree = rightLeftRotate(tree);
	            else
	                tree = leftRotate(tree);
	        }
		}
		return tree;
	}
	private static Node rightLeftRotate(Node tree) {
		tree.right = rightRotate(tree.right);
		tree = leftRotate(tree);
		return tree;
	}
	private static Node leftRightRotate(Node tree) {
		tree.left = leftRotate(tree.left);
	    tree = rightRotate(tree);
	    return tree;
	}
	private static Node leftRotate(Node tree) {
		Node temp = tree.right;
	    tree.right = temp.left;
	    temp.left = tree;
	    return temp;
	}
	private static Node rightRotate(Node tree) {
		Node temp = tree.left;
	    tree.left = temp.right;
	    temp.right = tree;
	    return temp;
	}
	private static int getHeight(Node tree) {
		if (tree == null) return 0;
	    int l = getHeight(tree.left);
	    int r = getHeight(tree.right);
	    return l > r ? l + 1 : r + 1;
	}
	
	static class Node {
		int val;
		Node left, right;
		Node (int v) {
			this.val = v;
		}
	}
}

总结

  • 对于二叉树Node内部类实现,一开始我是在Node类里添加了father这个属性,但是后期很容易就回路了,所以不建议这样;
  • AVL树,自己终于亲自实现了一遍,果然有底了不少。关于层次遍历里判断完全二叉树的逻辑,真是有点麻烦,很容易出现纰漏,看了大神的博客,发现还是有技巧的,那就是取名很关键,虽然就两个布尔变量,但是好的命名方式能让你思路异常清晰;
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值