数据结构(java)——二叉树的插入、遍历、删除、高度、叶子节点个数、判完全二叉树等操作

树是一个神奇的数据结构……

树的每个节点,都存在着多个指针,指向他的下一层,最后一层层下去通向叶子节点。

树是一个由有限个节点组成的一个具有层次关系的集合。他看起来像一棵倒着的树。

树里面的每个节点,会有一个父节点(上一层)和多个孩子节点(下一层)。

当然还会有数据域。。。数据域可以是多个。。

二叉树

其实重点就是二叉树,二叉树指的是,每个节点最多有2个分支,称为左孩子和右孩子。

所以,我们来看一下树的节点类。。。

我写的节点类里,包括了两个数据线(long和string,可以记录‘张三’,24岁之类的信息)

然后为了之后的一些乱七八糟的方法做准备。。。还有一个是标记有没有被访问过

public class Node {
	//long数据项
	public long data;
	//String数据项
	public String sData;
	//左孩子节点
	public Node leftChild;
	//右子节点
	public Node rightChild;
	//是否被访问
	public boolean wasVisited;
		
	//构造方法
	public Node(long data, String sData) {
		this.data = data;
		this.sData = sData;
	}
}

之后再看一些常用的方法吧。。。

由于树的方法比较多,我分开讲。。。最后合起来的所有代码再合起来一遍放在最后(包括test)

    首先是树的建立。。主要是,首先得有一个根节点,然后是插入节点的方法。插入按照排序插入,比父节点小的放在父节点的左边,比父节点大的放在右边,这样做的好处是后面讲的中序遍历可以直接排序。

public class Tree {
	
	//根节点
	public Node root;
	
	
	//插入一个节点
	public void insert(long data , String sData) {
		
		//封装节点
		Node newNode = new Node(data , sData);
		
		//两个引用
		//当前节点
		Node current = root;
		//父节点
		Node parent;
		
		//第一次插入直接赋值
		if(current == null) {
			root = newNode;
			return;
		}
		
		//循环左走右走
		while (true) {
			//父节点指向当前节点
			parent = current;
			//比较大小左右走
			if (current.data > data) {
				current = current.leftChild;
				if(current == null) {
					parent.leftChild = newNode;
					return;
				}
			}
			else {
				current = current.rightChild;
				if(current == null) {
					parent.rightChild = newNode;
					return;
				}
			}
		}
	}
}

下面的方法我就不写calss了,大家主要看一下思路,整体代码在最后面。

这里是根据数据查找节点的算法

//查找节点
	public Node find(long data) {
		//引用当前节点
		Node current = root;
		
		while(current.data != data) {
			//进行比较和当前节点大小
			if (current.data > data) {
				current = current.leftChild;				
			} else {
				current = current.rightChild;
			}
			
			//查不到
			if(current == null) {
				return null;
			}
		}
		return current;
	}
	

这里是一个重点,树的遍历,大家知道树的遍历有4种,前序,中序,后序,层序。

        前序:先跟,再左孩子,再右孩子。如果左(右)孩子是一棵子树,就吧左(右)子树当成现在的一颗树,进行跟,左孩子,右孩子的顺序遍历,以此类推。如果不懂的话,我会再写一篇关于三种遍历的文章,大家可以到我文章里看看。

        中序:先左孩子,再跟,再右孩子,和上面一样,如果有子树的情况,就吧子树当成当前状态继续中序遍历。

        后序:左孩子,右孩子,跟。

        层序:从上往下一层层遍历。。。。

这里提供了递归,和非递归的两种实现方法

	/*前序遍历
	 * 1.访问根节点
	 * 2.递归前序遍历左子树
	 * 3.递归前序遍历右子树
	 */
	public void frontOrder(Node localNode) {
		if(localNode != null) {
			System.out.print(localNode.data + "," + localNode.sData + " ; ");
			frontOrder(localNode.leftChild);
			frontOrder(localNode.rightChild);
		}
	}
	
	
	/*
	 * 中序遍历
	 * 1.递归中序遍历左子树
	 * 2.访问根节点
	 * 3.递归中序遍历右子树
	 */
	public void inOrder(Node localNode) {
		if (localNode != null) {
			inOrder(localNode.leftChild);
			System.out.print(localNode.data + "," + localNode.sData + " ; ");
			inOrder(localNode.rightChild);
		}
	}
	
	
	/*
	 * 后序遍历
	 * 1.递归后序遍历左子树
	 * 2.递归后序遍历右子树
	 * 3.访问根节点
	 */
	public void afterOrder(Node localNode) {
		if (localNode != null) {
			afterOrder(localNode.leftChild);
			afterOrder(localNode.rightChild);
			System.out.print(localNode.data + "," + localNode.sData + " ; ");
		}
	}
	
	
	//层序遍历
	public void LevelOrder(Node root) {
		Queue<Node> queue = new LinkedList<Node>();
		
		Node now = root;
		queue.add(root);
		
		while (!queue.isEmpty()) {
			now = queue.poll();
			if (now != null) {
				System.out.print(now.data + "," + now.sData + " ; ");
			}
			if (now.leftChild != null) {
				queue.add(now.leftChild);
			}
			if (now.rightChild != null) {
				queue.add(now.rightChild);
			}
		}
	}
	
	
	//利用栈
	//非递归遍历树_前序(根左右)
	public void FeiFrontOrder(Node root) {
		if (root == null) {
			return;
		}
		//定义栈,通过栈存放遍历的节点
		Stack<Node> stack = new Stack<Node>();
		stack.push(root);
		
		Node now = root.leftChild;
		
		while ( !stack.isEmpty()) {
			
			now = stack.pop();
			
			if (now != null) {
				System.out.print(now.data + "," + now.sData + " ; ");
				stack.push(now.rightChild);
				stack.push(now.leftChild);
			}
			
		}
		
	}
	
	
	//非递归遍历树_中序(左根右)
	public void FeiInOrder(Node root) {
		if (root == null) {
			return;
		}
		//定义栈,通过栈存放遍历的节点
		Stack<Node> stack = new Stack<Node>();
		stack.push(root);
		
		Node now = root.leftChild;
		
		while (now != null || !stack.isEmpty()) {
			
			if (now != null) {
				stack.push(now);
				now = now.leftChild;
			}
			else {
				now = stack.pop();
				System.out.print(now.data + "," + now.sData + " ; ");
				now = now.rightChild;
			}
		}
	}

	
	//非递归遍历树_后序(左右根)
	public void FeiAfterOrder(Node root) {
		if (root == null) {
			return;
		}
		
		Stack<Node> stack = new Stack<Node>();
		stack.push(root);
		
		Node visited = null;
		Node now = root.leftChild;
		
		while (now != null || !stack.isEmpty()) {
			while (null != now) {
				stack.push(now);
				now = now.leftChild;
			}
			now = stack.pop();
			if (now.rightChild == null || now.rightChild.wasVisited) {
				System.out.print(now.data + "," + now.sData + " ; ");
				now.wasVisited = true;
				now = null;
			} 
			else {
				stack.push(now);
				now = now.rightChild;
			}
		}
	}
	

理解了遍历的话。。。再看删除操作。。。

删除操作是比较复杂的,之后我会再开一个文章详细说删除操作的内容,这里先告诉大家,删除树的节点的时候,我们得找到一个中序后继节点来替换要删除的节点,以此来保持二叉树插入时候的平衡。代码如下

	//寻找中序后继节点
	public Node getHouJiNode(Node delNode) {
		//定义中序后继节点
		Node houji = delNode;
		//定义中序后继的父节点
		Node houjiparent = delNode;
		//当前节点
		Node current = delNode.rightChild;
		
		while(current != null) {
			houjiparent = houji;
			houji = current;
			current = current.leftChild;//往左边找
		}
		
		//把删除节点替换成终须后继节点
		//1.如果删除节点的右节点不是后继节点(正常右左左……找到的)
		if(houji != delNode.rightChild) {
			//中序后继的父节点的左子节点指向中序后继节点的右子节点(中序后继节点没有左子节点)
			houjiparent.leftChild = houji.rightChild;
			//后继的右边接上删除的右边,左边接上删除的左边
			houji.rightChild = delNode.rightChild;
			houji.leftChild = delNode.leftChild;
		}
		//2.删除节点的右节点就是中序后继节点,右边不用动,吧左边接上就可以
		else {
			houji.leftChild = delNode.leftChild;
		}
		
		return houji;
		
	}
	
	
	//删除节点delete
	public boolean delete(long data) {
		//引用当前节点
		Node current = root;
		
		//引用当前节点的父节点
		Node parent = root;
		
		//是左子节点还是右节点
		boolean isLeftChild = true;
		
		
		//循环找到要删的节点
		while (current.data != data) {
			
			parent = current;
			
			if (current.data > data) {
				current = current.leftChild;
				isLeftChild = true;
			} else {
				current = current.rightChild;
				isLeftChild = false;
			}
			
			//没有
			if(current == null) {
				return false;
			}		
		}
		//循环结束,current指向要删除节点,parent指向父节点
		
		
		
		//进行删除current节点
		
		//1.如果是叶子节点(没有子节点)
		if (current.leftChild == null &¤t.rightChild ==null) {
			if (current == root) {
				root = null;
			}
			//如果是左边的节点
			else if (isLeftChild) {
				parent.leftChild = null;
			}
			//如果是右边的节点
			else {
				parent.rightChild = null;
			}
		}
		
		//2.删除带有一个子节点的节点
		else if (current.rightChild == null) {
			//子节点是左子节点
			if (current == root) {
				root = current.leftChild;
			}
			else if (isLeftChild) {//删除的节点是左节点
				//把父节点的左子节点指向删除节点的左子节点(接上去)
				parent.leftChild = current.leftChild;
			}
			else {//删除的节点是右节点
				parent.rightChild = current.leftChild;
			}
		}
		else if (current.leftChild == null) {
			//子节点是右子节点
			if (current == root) {
				root = current.rightChild;
			}
			else if (isLeftChild) {//删除的节点是左节点
				parent.leftChild = current.rightChild;
			}
			else {//删除的节点是右节点
				parent.rightChild = current.rightChild;
			}
		}
		
		//3.删除有2个子节点的节点,需要寻找中续后继节点来替换删除节点
		else {
			Node houji = getHouJiNode(current);
			if (current == root) {
				root = houji;
			}
			else if (isLeftChild) {
				parent.leftChild = houji;
			}
			else {
				parent.rightChild = houji;
			}
		}
		
		return true;
	}
	

最后是一些乱七八糟的操作。。。

先是求k层有多少个,求叶子节点,求树的高度,没什么难度就不说了,主要靠递归遍历然后统计。。。

//求第k层节点的个数
	public int GetKLevelNode(Node root, int k) {
		if(1 > k) {
			return 0;
		}
		if (1 == k) {
			return 1;
		}
		else {
			return GetKLevelNode(root.leftChild, k - 1) + GetKLevelNode(root.rightChild, k - 1);
		}
	}
	
	
	//求叶子节点个数
	public int GetLeafCount(Node root) {
		if (root == null) {
			return 0;
		}
		if (root.leftChild == null && root.rightChild == null) {
			return 1;
		}else {
			return GetLeafCount(root.leftChild) + GetLeafCount(root.rightChild);
		}
	}
	
	
	//求树的高度
	public int BinTreeHeight(Node root) {
		//定义左右子树高度
		int leftHight = 0;
		int rightHight = 0;
		
		if (null == root.leftChild &&null == root.rightChild) {
			return 1;
		}
		
		//递归求左右子树高度
		leftHight = BinTreeHeight(root.leftChild);
		rightHight = BinTreeHeight(root.rightChild);
		//取最大值
		if (leftHight > rightHight) {
			return leftHight + 1;
		}
		else {
			return rightHight + 1;
		}
	}
	


下面是检测是否为完全二叉树,这里运用了层序遍历,设置一个boolean值after,完全二叉树层序遍历的话,从某个节点开始就会全是叶子节点,所以运用到这个思路,吧after改为true,这样之后遍历到的节点如果有孩子,就返回false。正常遍历下,如果有右孩子而没有左孩子的也不是完全二叉树,也返回false。具体看代码

//检测一颗树是不是完全二叉树
	public boolean IsCompleteBinTree(Node root) {
		boolean after = false;//表示层遍历从哪个节点之后需要全是叶子节点
		Queue<Node> queue = new LinkedList<Node>();
		
		Node now = root;
		queue.add(root);
		
		while (!queue.isEmpty()) {
			now = queue.poll();
			
			//如果必须要是叶子节点的时候,则如果有孩子节点就返回false
			if (after) {
				if (now.leftChild != null || now.rightChild != null) {
					return false;
				}
			}
			
			//如果某个节点有右孩子没有左孩子,false
			if (now.leftChild == null && now.rightChild != null) {
				return false;
			}
			
			if (now.leftChild != null) {
				queue.add(now.leftChild);
			}
			
			if (now.rightChild != null) {
				queue.add(now.rightChild);
			}else {
				//如果从某个节点开始没有右孩子了,需要之后都是叶子节点
				after = true;
			}
		}
		return true;
	}

这些是树的基本操作了,其他的更加复杂的操作以后再更。。。下面吧代码都贴上

记得每个类建一个.java文件,方便查看,我这里也是按照每个类有一个.java文件去写的,如果直接拷贝需要吧public去掉

node类:在最上面,已经发了

test:(这里也可以自己去测试,屏蔽的是做了每个内容的测试,所以大家自己看看)

public class TestTree {

	public static void main(String[] args) {
		Tree aTree = new Tree();
		Tree bTree = new Tree();
		
		aTree.insert(25, "e");
		aTree.insert(20, "d");
//		aTree.insert(28, "c");
//		aTree.insert(15, "c");
//		aTree.insert(30, "f");
//		aTree.insert(6, "c");
//		aTree.insert(45, "i");
//		aTree.insert(38, "c");
//		aTree.insert(32, "c");
//		aTree.insert(22, "c");
//		aTree.insert(10, "b");
//		aTree.insert(77, "c");
//		aTree.insert(40, "h");
//		aTree.insert(50, "j");
//		aTree.insert(18, "c");
//		aTree.insert(5, "a");
		
		
		
		System.out.println(aTree.GetLeafCount(aTree.root));
		
		System.out.println(aTree.IsCompleteBinTree(aTree.root));
		
//		bTree.root = bTree.CopyBinTree(aTree.root);
//		aTree.frontOrder(aTree.root);
//		System.out.println();
//		bTree.frontOrder(bTree.root);
		
		
		
//		aTree.LevelOrder(aTree.root);
//		aTree.frontOrder(aTree.root);
//		System.out.println();
//		aTree.FeiFrontOrder(aTree.root);
//		System.out.println();
//		aTree.inOrder(aTree.root);
//		System.out.println();
//		aTree.FeiInOrder(aTree.root);
//		System.out.println();
//		aTree.afterOrder(aTree.root);
//		System.out.println();
//		aTree.FeiAfterOrder(aTree.root);
		
		
//		aTree.insert(35, "g");
//		aTree.insert(10, "g");
//		aTree.insert(20, "g");
//		aTree.insert(15, "g");
//		aTree.insert(3, "g");
//		aTree.insert(4, "g");
//		aTree.insert(90, "g");
		
//		Node node = aTree.find(20);
//		System.out.println(node.data + " " + node.sData);
//		System.out.println(aTree.root.data);//10
//		System.out.println(aTree.root.leftChild.data);//3
//		System.out.println(aTree.root.rightChild.data);//20
//		System.out.println(aTree.root.rightChild.leftChild.data);//15

		
//		aTree.delete(10);
//		aTree.delete(20);
		
//		aTree.frontOrder(aTree.root);
//		System.out.println();
		
//		aTree.afterOrder(aTree.root);
//		System.out.println();
//		aTree.inOrder(aTree.root);
//		System.out.println();
	
		
//		TreeSet<Integer> tree = new TreeSet<Integer>();
//		
//		tree.add(Integer.valueOf(5));
//		tree.add(Integer.valueOf(4));
//		tree.add(Integer.valueOf(7));
//		tree.add(Integer.valueOf(2));
//		tree.add(Integer.valueOf(8));
//		tree.add(Integer.valueOf(6));
//		tree.add(Integer.valueOf(3));
//		tree.add(Integer.valueOf(1));
//		
//		
//		int a = tree.pollLast();
//		int b = tree.pollLast();
//		System.out.print(a +" " + b);
		
	}

}

tree类(这里400多行建议还是在上面自取所需)

import java.util.Stack;
import java.util.LinkedList;
import java.util.Queue;

//二叉树
public class Tree {
	
	//根节点
	public Node root;
	
	
	//插入一个节点
	public void insert(long data , String sData) {
		
		//封装节点
		Node newNode = new Node(data , sData);
		
		//两个引用
		//当前节点
		Node current = root;
		//父节点
		Node parent;
		
		//第一次插入直接赋值
		if(current == null) {
			root = newNode;
			return;
		}
		
		//循环左走右走
		while (true) {
			//父节点指向当前节点
			parent = current;
			//比较大小左右走
			if (current.data > data) {
				current = current.leftChild;
				if(current == null) {
					parent.leftChild = newNode;
					return;
				}
			}
			else {
				current = current.rightChild;
				if(current == null) {
					parent.rightChild = newNode;
					return;
				}
			}
		}
	}
	
	
	//二叉树拷贝,返回一个根
	public Node CopyBinTree(Node root) {
		Node newroot = new Node(root.data, root.sData);
		
//		Node now = newroot;
		
		if (root.leftChild != null) {
//			Node lnode = new Node(root.leftChild.data, root.leftChild.sData);
//			newroot.leftChild = lnode;
			Node lNode = CopyBinTree(root.leftChild);
			newroot.leftChild = lNode;
		}
		if (root.rightChild != null) {
//			Node rnode = new Node(root.rightChild.data, root.rightChild.sData);
//			newroot.rightChild = rnode;
			Node rNode = CopyBinTree(root.rightChild);
			newroot.rightChild = rNode;
		}
		return newroot;
	}

	
	//查找节点
	public Node find(long data) {
		//引用当前节点
		Node current = root;
		
		while(current.data != data) {
			//进行比较和当前节点大小
			if (current.data > data) {
				current = current.leftChild;				
			} else {
				current = current.rightChild;
			}
			
			//查不到
			if(current == null) {
				return null;
			}
		}
		return current;
	}
	

	/*前序遍历
	 * 1.访问根节点
	 * 2.递归前序遍历左子树
	 * 3.递归前序遍历右子树
	 */
	public void frontOrder(Node localNode) {
		if(localNode != null) {
			System.out.print(localNode.data + "," + localNode.sData + " ; ");
			frontOrder(localNode.leftChild);
			frontOrder(localNode.rightChild);
		}
	}
	
	
	/*
	 * 中序遍历
	 * 1.递归中序遍历左子树
	 * 2.访问根节点
	 * 3.递归中序遍历右子树
	 */
	public void inOrder(Node localNode) {
		if (localNode != null) {
			inOrder(localNode.leftChild);
			System.out.print(localNode.data + "," + localNode.sData + " ; ");
			inOrder(localNode.rightChild);
		}
	}
	
	
	/*
	 * 后序遍历
	 * 1.递归后序遍历左子树
	 * 2.递归后序遍历右子树
	 * 3.访问根节点
	 */
	public void afterOrder(Node localNode) {
		if (localNode != null) {
			afterOrder(localNode.leftChild);
			afterOrder(localNode.rightChild);
			System.out.print(localNode.data + "," + localNode.sData + " ; ");
		}
	}
	
	
	//层序遍历
	public void LevelOrder(Node root) {
		Queue<Node> queue = new LinkedList<Node>();
		
		Node now = root;
		queue.add(root);
		
		while (!queue.isEmpty()) {
			now = queue.poll();
			if (now != null) {
				System.out.print(now.data + "," + now.sData + " ; ");
			}
			if (now.leftChild != null) {
				queue.add(now.leftChild);
			}
			if (now.rightChild != null) {
				queue.add(now.rightChild);
			}
		}
	}
	
	
	//利用栈
	//非递归遍历树_前序(根左右)
	public void FeiFrontOrder(Node root) {
		if (root == null) {
			return;
		}
		//定义栈,通过栈存放遍历的节点
		Stack<Node> stack = new Stack<Node>();
		stack.push(root);
		
		Node now = root.leftChild;
		
		while ( !stack.isEmpty()) {
			
			now = stack.pop();
			
			if (now != null) {
				System.out.print(now.data + "," + now.sData + " ; ");
				stack.push(now.rightChild);
				stack.push(now.leftChild);
			}
			
		}
		
	}
	
	
	//非递归遍历树_中序(左根右)
	public void FeiInOrder(Node root) {
		if (root == null) {
			return;
		}
		//定义栈,通过栈存放遍历的节点
		Stack<Node> stack = new Stack<Node>();
		stack.push(root);
		
		Node now = root.leftChild;
		
		while (now != null || !stack.isEmpty()) {
			
			if (now != null) {
				stack.push(now);
				now = now.leftChild;
			}
			else {
				now = stack.pop();
				System.out.print(now.data + "," + now.sData + " ; ");
				now = now.rightChild;
			}
		}
	}

	
	//非递归遍历树_后序(左右根)
	public void FeiAfterOrder(Node root) {
		if (root == null) {
			return;
		}
		
		Stack<Node> stack = new Stack<Node>();
		stack.push(root);
		
		Node visited = null;
		Node now = root.leftChild;
		
		while (now != null || !stack.isEmpty()) {
			while (null != now) {
				stack.push(now);
				now = now.leftChild;
			}
			now = stack.pop();
			if (now.rightChild == null || now.rightChild.wasVisited) {
				System.out.print(now.data + "," + now.sData + " ; ");
				now.wasVisited = true;
				now = null;
			} 
			else {
				stack.push(now);
				now = now.rightChild;
			}
		}
	}
	
	
	
	//寻找中序后继节点
	public Node getHouJiNode(Node delNode) {
		//定义中序后继节点
		Node houji = delNode;
		//定义中序后继的父节点
		Node houjiparent = delNode;
		//当前节点
		Node current = delNode.rightChild;
		
		while(current != null) {
			houjiparent = houji;
			houji = current;
			current = current.leftChild;//往左边找
		}
		
		//把删除节点替换成终须后继节点
		//1.如果删除节点的右节点不是后继节点(正常右左左……找到的)
		if(houji != delNode.rightChild) {
			//中序后继的父节点的左子节点指向中序后继节点的右子节点(中序后继节点没有左子节点)
			houjiparent.leftChild = houji.rightChild;
			//后继的右边接上删除的右边,左边接上删除的左边
			houji.rightChild = delNode.rightChild;
			houji.leftChild = delNode.leftChild;
		}
		//2.删除节点的右节点就是中序后继节点,右边不用动,吧左边接上就可以
		else {
			houji.leftChild = delNode.leftChild;
		}
		
		return houji;
		
	}
	
	
	//删除节点delete
	public boolean delete(long data) {
		//引用当前节点
		Node current = root;
		
		//引用当前节点的父节点
		Node parent = root;
		
		//是左子节点还是右节点
		boolean isLeftChild = true;
		
		
		//循环找到要删的节点
		while (current.data != data) {
			
			parent = current;
			
			if (current.data > data) {
				current = current.leftChild;
				isLeftChild = true;
			} else {
				current = current.rightChild;
				isLeftChild = false;
			}
			
			//没有
			if(current == null) {
				return false;
			}		
		}
		//循环结束,current指向要删除节点,parent指向父节点
		
		
		
		//进行删除current节点
		
		//1.如果是叶子节点(没有子节点)
		if (current.leftChild == null &¤t.rightChild ==null) {
			if (current == root) {
				root = null;
			}
			//如果是左边的节点
			else if (isLeftChild) {
				parent.leftChild = null;
			}
			//如果是右边的节点
			else {
				parent.rightChild = null;
			}
		}
		
		//2.删除带有一个子节点的节点
		else if (current.rightChild == null) {
			//子节点是左子节点
			if (current == root) {
				root = current.leftChild;
			}
			else if (isLeftChild) {//删除的节点是左节点
				//把父节点的左子节点指向删除节点的左子节点(接上去)
				parent.leftChild = current.leftChild;
			}
			else {//删除的节点是右节点
				parent.rightChild = current.leftChild;
			}
		}
		else if (current.leftChild == null) {
			//子节点是右子节点
			if (current == root) {
				root = current.rightChild;
			}
			else if (isLeftChild) {//删除的节点是左节点
				parent.leftChild = current.rightChild;
			}
			else {//删除的节点是右节点
				parent.rightChild = current.rightChild;
			}
		}
		
		//3.删除有2个子节点的节点,需要寻找中续后继节点来替换删除节点
		else {
			Node houji = getHouJiNode(current);
			if (current == root) {
				root = houji;
			}
			else if (isLeftChild) {
				parent.leftChild = houji;
			}
			else {
				parent.rightChild = houji;
			}
		}
		
		return true;
	}
	
	
	//求第k层节点的个数
	public int GetKLevelNode(Node root, int k) {
		if(1 > k) {
			return 0;
		}
		if (1 == k) {
			return 1;
		}
		else {
			return GetKLevelNode(root.leftChild, k - 1) + GetKLevelNode(root.rightChild, k - 1);
		}
	}
	
	
	//求叶子节点个数
	public int GetLeafCount(Node root) {
		if (root == null) {
			return 0;
		}
		if (root.leftChild == null && root.rightChild == null) {
			return 1;
		}else {
			return GetLeafCount(root.leftChild) + GetLeafCount(root.rightChild);
		}
	}
	
	
	//求树的高度
	public int BinTreeHeight(Node root) {
		//定义左右子树高度
		int leftHight = 0;
		int rightHight = 0;
		
		if (null == root.leftChild &&null == root.rightChild) {
			return 1;
		}
		
		//递归求左右子树高度
		leftHight = BinTreeHeight(root.leftChild);
		rightHight = BinTreeHeight(root.rightChild);
		//取最大值
		if (leftHight > rightHight) {
			return leftHight + 1;
		}
		else {
			return rightHight + 1;
		}
	}
	
	
	//检测一个节点是否在二叉树中
	public boolean IsInTree(Node root, Node pNode) {
		boolean is = false;
		Node aNode = find(pNode.data);
		if (aNode.sData.equals(pNode.sData)) {
			is = true;
		}
		return is;
	}
	
	
	//检测一颗树是不是完全二叉树
	public boolean IsCompleteBinTree(Node root) {
		boolean after = false;//表示层遍历从哪个节点之后需要全是叶子节点
		Queue<Node> queue = new LinkedList<Node>();
		
		Node now = root;
		queue.add(root);
		
		while (!queue.isEmpty()) {
			now = queue.poll();
			
			//如果必须要是叶子节点,则如果有节点就返回false
			if (after) {
				if (now.leftChild != null || now.rightChild != null) {
					return false;
				}
			}
			
			//如果某个节点有右孩子没有左孩子,false
			if (now.leftChild == null && now.rightChild != null) {
				return false;
			}
			
			if (now.leftChild != null) {
				queue.add(now.leftChild);
			}
			
			if (now.rightChild != null) {
				queue.add(now.rightChild);
			}else {
				//如果从某个节点开始没有右孩子了,需要之后都是叶子节点
				after = true;
			}
		}
		return true;
	}

}

猜你喜欢

转载自blog.csdn.net/likunkun__/article/details/80183599