剑指offer: 树的遍历 (java)

二叉树基本概念

二叉树基本概念:
  1) 节点的度。节点所拥有子树的个数称为该节点的度。
  2) 叶节点。度为0的节点。
  3) 分支节点。度不为0的节点。
  4) 节点的层数。规定树的根节点层数为1,其余节点的层数为其双亲节点的层数+1。
  5) 树的深度。树中所有节点的最大层数为树的深度。
  6) 树的度。树中各节点度的最大值为该树的度。 
  7) 满二叉树。在一棵二叉树中,所有分支节点都有左子树和右子树,且所有叶节点在同一层上。
  8) 完全二叉树。一个深度为k有n个节点的二叉树,对树中的节点从上到下从左到右的顺序进行编号,若编号i
     的节点与满二叉树中编号为i的节点位置相同,那么这棵二叉树被称为完全二叉树。
  1) 一棵非空二叉树的第i层上最多有2^(i-1)个节点。(i>=1)
  2) 一棵深度为k的二叉树中,最多具有2^k-1个节点,最少有k个节点。
  3) 对于一棵非空二叉树,叶节点数n0(度为0的节点),总比度为2的节点n2数多一个。即n0=n2+1;
     (二叉树总的节点数n,叶节点数为n0,度为1的节点数n1,度为2的节点数n2) n=n0+n1+n2;
     二叉树性质:n=所有节点读书之和+1,即n=n1+2*n2+1   由上两式得:n0 = n2 + 1
  4) 具有n个节点的完全二叉树的深度为[log2 n] + 1
  5) 对于具有n个节点的完全二叉树,若编号从1开始,则对于任一的序号为i的节点:
     若i>1,那么序号i的双亲节点为i/2(整除);若i=1,则此节点为根节点,无双亲节点。
     序号为i的节点的   左孩子序号为2*i(2*i<=n), 右孩子的序号为2*+1(2*i+1<=n)
     若编号从0开始,则对于任一的序号为i的节点:那么,序号i的双亲节点为(i-1)/2,左孩子的编号为2*i+1,
     右孩子的编号为2*i+2.
                
排序二叉树:
  1) 若左子树不为空,那么左子树上所有节点的值均小于它根节点的值。
  2) 若右子树不为空,那么右子树上所有节点的值均大于它根节点的值。

 

   运用:递归、非递归实现先中后序遍历

   代码:

// 递归实现--先序遍历
public  void preOrderrecur(Node head) {
	if(head == null) { return ;}
	System.out.print(head.value+"  ");
	preOrderrecur(head.left);
	preOrderrecur(head.right);
}

// 非递归实现--先序遍历
public  void preOrderUnrecur(Node head) {
	System.out.print("pre--Order"+"  ");
	if(head != null) {
		Stack<Node> stack = new Stack<Node>();   // 申请一个栈
		stack.push(head);                        // 将根节点压入栈中
		while(!stack.isEmpty()) {                // 条件-栈不为空
			head = stack.pop();                  // 抛出栈顶节点
			System.out.print(head.value+"  ");   // 打印该节点
			// 注意顺序不可变
			if(head.right != null) { stack.push(head.right); } // 若有右节点,先存右节点 
			if(head.left != null) { stack.push(head.left); }	
		}
	}
	System.out.println();
}
// 递归实现--中序遍历
public  void inOrderrecur(Node head) {
	if(head == null) {return ;}
	inOrderrecur(head.left);
	System.out.print(head.value+"  ");
	inOrderrecur(head.right);
}

// 非递归实现--中序遍历
public  void inOrderUnrecur(Node head){
	System.out.print("in -- Order"+"  ");
	if(head != null) {
		Stack<Node> stack = new Stack<Node>();     // 申请栈
		while(!stack.isEmpty() || head != null) {
			if(head != null) {          // head 不为空时,将head存储到栈中,继续往左走。
				stack.push(head);
				head = head.left;
			}else{                      // head 为空时, 从栈中弹出一个元素,并打印,往右走。
				head = stack.pop();
				System.out.print(head.value+"  ");
				head = head.right;
			}
		}
	}
	System.out.println();
}
// 递归实现--后序遍历
public  void posOrderrecur(Node head) {
	if(head == null) {return ;}
	posOrderrecur(head.left);
	posOrderrecur(head.right);
	System.out.print(head.value+"  ");
}

// 非递归实现--后序遍历
public  void posOrderUnrecur(Node head) {
	System.out.print("pos-order: "+"  ");
	if(head == null) { return; }
	if(head != null) {
		Stack<Node> stack = new Stack<Node>();
		Stack<Node> stack1 = new Stack<Node>();
		stack.push(head);
		while(!stack.isEmpty()) {
			head = stack.pop();
			stack1.push(head);
			if( head.left != null) { 
				stack.push(head.left);
			}
			if(head.right != null) { 
				stack.push(head.right);
			}
		}
		while(!stack1.isEmpty()) {
			System.out.print(stack1.pop().value+"  ");
		}
	}
	System.out.println();
}
// 层序遍历   使用队列来实现    先将 根节点 放入队列中,然后每次从队列中取出一个节点打印该节点,若该节点有子节点,
// 将子节点放入队尾,直到队列为空。
public void layerTranverse(Node root) {
	if(root == null) { return; }
	Queue<Node> queue = new LinkedList<Node>();  // 申请一个队列
	queue.add(root);                             // 先将根节点放入队列
	while(!queue.isEmpty()) {
		Node node = queue.poll();                // 出队列
		System.out.print(node.value+" ");
		if(node.left != null) {                  // node左子树不为空,入队
			queue.add(node.left);
		}
		if(node.right != null) {                 // node右子树不为空,入队
			queue.add(node.right);
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值