秋招总结。
文章目录
二叉树
二叉树是每个结点最多有两个子树的树结构。 一棵深度为k,且有 2^k-1
个结点的二叉树,称为满二叉树。这种树的特点是每一层上的结点数都是最大结点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且或者最后一层是满的,或者是在右边缺少连续若干结点,则此二叉树为完全二叉树。具有n个结点的完全二叉树的深度为floor(log2n)+1。深度为k的完全二叉树,至少有2^(k-1)
个叶子结点,至多有2^k-1
个结点。
二叉树的构建以及三种遍历方式
- 要求:把一个数组的值存入二叉树中,然后进行3种方式的遍历打印。
import java.util.LinkedList;
import java.util.List;
/**
* 功能:把一个数组的值存入二叉树中,然后进行3种方式的遍历
* 参考资料0:数据结构(C语言版)严蔚敏
* 参考资料1:http://zhidao.baidu.com/question/81938912.html
* 参考资料2:http://cslibrary.stanford.edu/110/BinaryTrees.html#java
*
*/
public class BinTreeTraverse2 {
private int[] array = {
1, 2, 3, 4, 5, 6 };
private static List<Node> nodeList = null;
/**
* 内部类:节点
*/
private static class Node {
Node leftChild;
Node rightChild;
int data;
Node(int newData) {
leftChild = null;
rightChild = null;
data = newData;
}
}
public void createBinTree() {
nodeList = new LinkedList<Node>();
// 将一个数组的值依次转换为Node节点
for (int nodeIndex = 0; nodeIndex < array.length; nodeIndex++) {
nodeList.add(new Node(array[nodeIndex]));
}
// 对前lastParentIndex-1个父节点按照父节点与孩子节点的数字关系建立二叉树
for (int parentIndex = 0; parentIndex < array.length / 2 - 1; parentIndex++) {
// 左孩子
nodeList.get(parentIndex).leftChild = nodeList
.get(parentIndex * 2 + 1);
// 右孩子
nodeList.get(parentIndex).rightChild = nodeList
.get(parentIndex * 2 + 2);
}
// 最后一个父节点:因为最后一个父节点可能没有右孩子,所以单独拿出来处理
int lastParentIndex = array.length / 2 - 1;
// 左孩子
nodeList.get(lastParentIndex).leftChild = nodeList
.get(lastParentIndex * 2 + 1);
// 右孩子,如果数组的长度为奇数才建立右孩子
if (array.length % 2 == 1) {
nodeList.get(lastParentIndex).rightChild = nodeList
.get(lastParentIndex * 2 + 2);
}
}
/**
* 先序遍历
* 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已
* @param node 遍历的节点
*/
public static void preOrderTraverse(Node node) {
if (node == null)
return;
System.out.print(node.data + " ");
preOrderTraverse(node.leftChild);
preOrderTraverse(node.rightChild);
}
/**
* 中序遍历
* 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已
* @param node 遍历的节点
*/
public static void inOrderTraverse(Node node) {
if (node == null)
return;
inOrderTraverse(node.leftChild);
System.out.print(node.data + " ");
inOrderTraverse(node.rightChild);
}
/**
* 后序遍历
* 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已
* @param node 遍历的节点
*/
public static void postOrderTraverse(Node node) {
if (node == null)
return;
postOrderTraverse(node.leftChild);
postOrderTraverse(node.rightChild);
System.out.print(node.data + " ");
}
public static void main(String[] args) {
BinTreeTraverse2 binTree = new BinTreeTraverse2();
binTree.createBinTree();
// nodeList中第0个索引处的值即为根节点
Node root = nodeList.get(0);
System.out.println("先序遍历:");
preOrderTraverse(root);
System.out.println();
System.out.println("中序遍历:");
inOrderTraverse(root);
System.out.println();
System.out.println("后序遍历:");
postOrderTraverse(root);
}
}
运行结果:
先序遍历:
1 2 4 5 3 6
中序遍历:
4 2 5 1 6 3
后序遍历:
4 5 2 6 3 1
- 要求:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
//前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
if(startPre>endPre||startIn>endIn)
return null;
TreeNode root=new TreeNode(pre[startPre]);
for(int i=startIn;i<=endIn;i++)
if(in[i]==pre[startPre]){
root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
}
return root;
}
- 要求:非递归先序遍历
public static void preOrder2(Node root)
{
// 前序遍历,"根左右"
Stack<Node> s = new Stack<Node>();
if(root != null)
{
s.push(root);
while(!s.isEmpty())
{
Node c = s.pop();
System.out.print(c.data + "->");
if(c.right != null)
{
s.push(c.right);
}
if(c.left != null)
{
s.push(c.left);
}
}
}
}
- 要求:非递归中序遍历
public void inOrder() {
Node current = root;
//把LinkedList作为栈使用
LinkedList<Node> s = new LinkedList<Node>();
while (current != null || !s.isEmpty()) {
while (current != null) {
s.addFirst(current);
current = current.left;
}
if (!s.isEmpty()) {
current = s.removeFirst();
System.out.print(current.data + " -> ");
current = current.right;
}
}
}
- 要求:后序遍历非递归
public static void postOrder2(Node root)
{
// 后序遍历,"左右根"
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();
if(root != null)
{
s1.push(root);
while(!s1.empty())
{
root = s1.pop();
s2.push(root);
if(root.left != null)
{
s1.push(root.left);
}
if(root.right != null)
{
s1.push(root.right);
}
}
while(!s2.empty())
{
System.out.print(s2.pop().data + "->");
}
}
}
二叉树的打印
- 要求:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if(pRoot == null){
return result;
}
Queue<TreeNode> layer = new LinkedList<TreeNode>();
ArrayList<Integer> layerList = new ArrayList<Integer>();
layer.add(pRoot);
int start = 0, end = 1;
while(!layer.isEmpty()){
TreeNode cur = layer.remove();
layerList.add(cur.val);
start++;
if(cur.left!=null){
layer.add(cur.left);
}
if(cur.right!=null){
layer.add(cur.right);
}
if(start == end){
end = layer.size();
start = 0;
result.add(layerList);
layerList = new ArrayList<Integer>();
}
}
return result;
}
- 要求:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(root == null) return list;
Deque<TreeNode> deque = new LinkedList<TreeNode>();
deque.add(root);
while(!deque.isEmpty()){
TreeNode t = deque.pop();
list.add(t.val);
if(t.left != null) deque.add(t.left);
if(t.right != null) deque.add(t.right);
}
return list;
}
- 要求:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
if (pRoot == null) {
return ret;
}
ArrayList<Integer> list = new ArrayList<>();
LinkedList<TreeNode> queue = new LinkedList<>();
queue.addLast(null);//层分隔符
queue.addLast(pRoot);
boolean leftToRight = true;
while (queue.size() != 1) {
TreeNode node = queue.removeFirst();
if (node == null) {
//到达层分隔符
Iterator<TreeNode> iter = null;
if (leftToRight) {
iter = queue.iterator();//从前往后遍历
} else {
iter = queue.descendingIterator();//从后往前遍历
}
leftToRight = !leftToRight;
while (iter.hasNext()) {
TreeNode temp = (TreeNode)iter.next();
list.add(temp.val);
}
ret.add(new ArrayList<Integer>(list));
list.clear();
queue.addLast(null);//添加层分隔符
continue;//一定要continue
}
if (node.left != null) {
queue.addLast(node.left);
}
if (node.right != null) {
queue.addLast(node.right);
}
}
return ret;
}
二叉树的节点查找
- 要求:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
public TreeLinkNode GetNext(TreeLinkNode node)
{
if(node==null)return null;
if(node.right!=null)
{
node=node.right;
while(node.left!=null)
{
node=node.left;
}return node;
}
while(node.next!=null)
{
if(node.next.left==node)return node.next;
node