码迷,mamicode.com
首页 > 其他好文 > 详细

关于二叉树的常见题型

时间:2016-07-17 00:46:59      阅读:358      评论:0      收藏:0      [点我收藏+]

标签:

一、二叉树相关概念

1.1 基本术语

  • 结点的度:一个结点的子结点的个数称为结点的度。
  • 树的度:树中结点的最大度数为树的度
  • 树的深度(高度):树中结点的最大层数,从1开始。

1.2 二叉树分类

  • 满二叉树:一颗高度为h,并且含有2^h-1个结点的二叉树称为满二叉树。即树中每一层都含有最多的节点。除叶子节点每个节点的度都为2
  • 完全二叉树:当高度为h具有n个结点的二叉树,与高度为h的满二叉树结点编号完全对应时,即为完全二叉树。(若存在度为1的节点,只能有一个,且只有左孩子无右孩子)
  • 二叉排序树:左子树上所有的结点的关键字均小于根节点的关键字,右子树上所有节点的关键字均大于根结点的关键字。(中序遍历可得到递增序列)
  • 平衡二叉树:树上任一结点的左子树和右子树深度之差不超过1
  • 哈夫曼树:在含有n个带权叶子节点的二叉树中,其中带权路径长度最小的二叉树为哈夫曼树(最优二叉树)—哈夫曼编码
  • 红黑树:红黑树是每个节点都带颜色的树,节点颜色或是红色或是黑色,红黑树是查找树。最重要的性质,从根节点到叶子节点的最长的路径不多于最短路径的长度的2倍。红黑树插入、查找、删除的时间复杂度都为O(logn)

1.3 二叉树的几条重要性质:

  1.  非空二叉树上叶子节点的个数等于度数为2的节点数+1   
  2. 结点i所在的层次(深度)为 (logn)+1
  3. N个节点的二叉树的高度为(logn)+1或是log(n+1)

1.4 二叉树的常见面试题

注意事项:

  •  根节点是否为空(递归结点是否为null)
  • 是否只存在根节点(一个节点)
  • 二叉树通常使用递归,清楚递归结束的条件。例如找路径时是遇到叶子节点停止,大多数是当前结点为null
题目汇总

  1. 二叉树的遍历:前序遍历、中序遍历、后序遍历、层次遍历(队列)
  2. 根据中序遍历序列和前序遍历序列(或后序遍历)重建二叉树。
  3. 求二叉树的所有路径(根到叶子节点)
  4. 判断二叉树中是否存在一条路径使得节点之和为给定的值。
  5. 求二叉树的最大深度、最小深度
  6. 求二叉树第k的节点个数(层次遍历:队列)
  7. 求二叉树中叶子节点的个数
  8. 交换二叉树的左右孩子
  9.  判断两棵二叉树是否相同(结构和值都相等)

  10.  判断二叉树是否为完全二叉树

  11. 判断二叉树是否为平衡二叉树

  12. 求二叉树的镜像

  13. 求二叉树中节点的最大距离

  14. 哈夫曼树的构建

  15. 将二叉查找树变为有序的双向链表

  16. 求二叉树中两个节点的最低公共祖先节点

  17. 输入两棵二叉树AB,判断B是否为A的子树

详细代码
  1. 二叉树的遍历:前序遍历、中序遍历、后序遍历、层次遍历(队列)
前序遍历:
//递归:前序遍历
	public void preOrder(Node node){
		if(node!=null){
			System.out.print(node.getPerson().getKey()+"\t");
			preOrder(node.getLeftChild());
			preOrder(node.getRightChild());
		}
	}
	
	//非递归:前序遍历
	private void preOrder_2(){
		Node curNode = rootNode;
		while(curNode!=null){
			//打印当前节点
			System.out.print(curNode.getPerson().getKey()+"\t");
			//入栈
			stack.push(curNode);
			//指向左子节点
			curNode = curNode.getLeftChild();
			//查找最左边的子节点
			while(curNode == null&&!stack.isEmpty()){
				curNode = stack.peek();//取栈顶元素
				stack.pop();//出栈
				curNode = curNode.getRightChild();
			}
		}
	}

中序遍历:
<span style="white-space:pre">	</span>//递归:中序遍历
	public void midOrder(Node node){
		if(node!=null){
			midOrder(node.getLeftChild());
			System.out.print(node.getPerson().getKey()+"\t");
			midOrder(node.getRightChild());
		}
	}
	//非递归:中序遍历(左根右)
	public void midOrder_2(){
		Node curNode = rootNode;
		while(curNode!=null||!stack.isEmpty()){
			if(curNode.getLeftChild()!=null){
				stack.push(curNode);
				curNode = curNode.getLeftChild();
			}else {
				//打印最左端的节点
				System.out.print(curNode.getPerson().getKey()+"\t");
				curNode = curNode.getRightChild();//指向右子节点
				while(curNode == null&&!stack.isEmpty()){
					curNode = stack.peek();
					System.out.print(curNode.getPerson().getKey()+"\t");
					stack.pop();
					curNode = curNode.getRightChild();
				}
			}
		}
	}
后序遍历:
//递归:后序遍历
	public void behOrder(Node node){
		if (node!=null) {
			behOrder(node.getLeftChild());
			behOrder(node.getRightChild());
			System.out.print(node.getPerson().getKey()+"\t");
		}
	}
	//非递归:后序遍历(左根右)
	public void behOrder_2(){
		Node curNode = rootNode;
		Node preNode = null;
		//先将根入栈
		stack.push(curNode);
		while(!stack.isEmpty()){
			curNode = stack.peek();//当前节点设置为栈顶节点
			if(curNode.getLeftChild()==null&&curNode.getRightChild()==null
			||(preNode!=null&&(curNode.getLeftChild()==preNode||curNode.getRightChild()==preNode))){
				//当前节点无左右节点,或者有左节点或右节点,但已经被访问过
				//则直接输出该节点,将其出栈,将其设为上一个访问的节点
				System.out.print(curNode.getPerson().getKey()+"\t");
				stack.pop();
				preNode = curNode;//已被访问过
			}else {
				//如果不满足上面两种情况,则将其右孩子左孩子依次入栈(先右节点再左节点)
				if (curNode.getRightChild()!=null) {
					stack.push(curNode.getRightChild());
				}
				if(curNode.getLeftChild()!=null){
					stack.push(curNode.getLeftChild());
				}
			}
		}
	}
层次遍历:
<span style="white-space:pre">	</span>public int levelOrder(TreeNode root,int k) {
		Queue  queue = new Queue(1024);
        List<List<Integer>> list = new ArrayList<List<Integer>>();
		if(root==null){
			return 0;
		}
        
        queue.push(root);
        //每层节点集
        List<Integer> level = new ArrayList<Integer>();
        //每层的节点个数
        int number = 0;
        int levelCount = 0;
        do{
        	Queue  queue2 = new Queue(1024);
        	while(!queue.isEmpty()){
            	//取队首节点
            	TreeNode head = queue.peek();
            	level.add(head.val);
            	number++;//结点个数加1
            	//弹出队头
            	queue.pop();
            	
            	if(head.left!=null){
            		queue2.push(head.left);
            	}
            	if(head.right!=null){
            		queue2.push(head.right);
            	}
            }
        	levelCount++;//层级加1
        	if(levelCount==k){
        		return number;
        	}
        	
        	list.add(level);
        	level = new ArrayList<Integer>();
        	number = 0;
        	queue = queue2;
        }while(!queue.isEmpty());
        return number;
    }
	
	public class Queue {
		/**
		 * 实现队列
		 */
		int first,last,maxSize;
		TreeNode[] queue;
		public Queue(int size){
			first = last = -1;
			maxSize = size;
			queue = new TreeNode[maxSize];
		}
		public boolean isEmpty(){
			if(first==-1){
				return true;
			}else {
				return false;
			}
		}
		public boolean isFull(){
			if(first==(last+1)%maxSize){
				return true;
			}else {
				return false;
			}
		}
		//push
		public boolean push(TreeNode num){
			if(this.isFull()){
				System.out.println("queue is full!");
				return false;
			}if(this.isEmpty()){
				first = last = 0;
			}else{
				last = (last+1)%maxSize;
			}
			queue[last] = num;
			
			return true;
		}
		
		public TreeNode pop(){
			TreeNode num = queue[first];
			if(this.isEmpty()){
				queue = new TreeNode[maxSize];
				return null;
			}
			if(first==last){
				//到达队尾,清空数组
				queue = new TreeNode[maxSize];
				first = last = -1;
				return num;
			}
			
			first=(first+1)%maxSize;
			return num;	
		}
		
		public TreeNode peek(){
			if(first==-1) return null;
			else return queue[first];
		}
	}


  1. 根据中序遍历序列和前序遍历序列(或后序遍历)重建二叉树。
  2. 求二叉树的所有路径(根到叶子节点)
  3. 判断二叉树中是否存在一条路径使得节点之和为给定的值。
  4. 求二叉树的最大深度、最小深度
  5. 求二叉树第k的节点个数(层次遍历:队列)
  6. 求二叉树中叶子节点的个数
  7. 交换二叉树的左右孩子
  8.  判断两棵二叉树是否相同(结构和值都相等)

  9.  判断二叉树是否为完全二叉树

  10. 判断二叉树是否为平衡二叉树

  11. 求二叉树的镜像

  12. 求二叉树中节点的最大距离

  13. 哈夫曼树的构建

  14. 将二叉查找树变为有序的双向链表

  15. 求二叉树中两个节点的最低公共祖先节点

  16. 输入两棵二叉树AB,判断B是否为A的子树











关于二叉树的常见题型

标签:

原文地址:http://blog.csdn.net/u010796790/article/details/51926166

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!