java编写非递归与递归创建有序的二叉树

Posted 小牛儿帥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java编写非递归与递归创建有序的二叉树相关的知识,希望对你有一定的参考价值。

java非递归与非递归创建有序的二叉树

在这里插入图片描述

二叉树

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分 。
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点

二叉树是数据结构中的线性存储的结构,那什么叫有序的二叉树呢?不然就是在存储数据的时候是按照数据大小进行存储,在java语言中也存在此结构的类ThreeSet类,它是一个容器,用来存放数据且其中不能存放相同元素,因为.二叉树认为能够存放在树形结构中的元素都是有序元素。例如定义一组数据{7,2,8,1,4,3,5},在树形结构中如下图所示。
在这里插入图片描述
二叉树的遍历过程中有三种方式,分别是先序、中序和后序,通常情况下要熟悉三种遍历的方式。一般中序输出是有顺序的,从小到大或者从大到小。
现在我们需要构建一颗普通二叉树(不具有顺序)

二叉树的创建

二叉树实则是一颗倒立着的树,拥有结点、左右子结点,所以构建二叉树的结构具有很多方式,而二叉树的样式也有很多,接下来重点介绍三种不同方式创建二叉树,分别是普通无序二叉树,有序递归和有序非递归创建二叉树。

二叉树的成员变量

构建基本的成员变量

public class Node {//构建一个二叉树结点类
	public Node leftNode;//左节点
	public Node rightNode;//右节点
	public int data;//结点里存放的数据
	public Node root;//根节点
	public List<Node>datas;//构建结点的集合
	public Node() {//无参的构造方法
	}
	public Node(Node leftNode,Node rightNode,int date) {//初始化一个结点
		this.leftNode=leftNode;
		this.rightNode=rightNode;
		this.date=date;
	}
	public Node(int date) {//初始化只包含一个数据的结点
		this(null,null,date);
	}
}

接下来构建普通的二叉树方法(非递归)

public void createNode(int[] arr){
datas = new ArrayList<Node>();
for(int i:arr){
datas.add(new Node(i));
}
root = datas.get(0);//初始化根节点
for(int i=0;i<arr.length;i++){
datas.get(i).leftNode=datas.get(2*i+1);//建立左节点
if(2*i+2<arr.length){//防止下标越界
datas.get(i).rightNode = datas.get(2*i+2);//建立右节点
}
}
}

递归创建普通二叉树

public void createNodeN(Node n,int i){//平衡二叉树
	if(leftNode==null&&rightNode!=null){
		leftNode=node;
	}else if(leftNode!=null&&rightNode==null){
		rightNode=node;
	}else if(leftNode==null&&rightNode==null){
		leftNode=node;
	}else{
	if(i%2==0)
		leftNode.createNode(node,i++);
	esle
		rightNode.createNode(node,i++);
	}
}

构建有序的二叉树(递归创建)

第一种方式

public void createNodeRecursive(int[] arr,int index){//根结点调用此方法,默认根节点存在,index数组下标,从1开始
	if(index>arr.length){//边界条件
		return;
	}
	if(arr[index]<data){//如果当前结点的数据大于将排序的结点
		if(leftNode==null){//当前this结点的左节点为空
			leftNode = new Node(arr[index++]);
		}else{//寻找下一个空结点
			leftNode.createNodeRecusive(arr,index);
		}
	}else{//当前this结点小于排序结点
		if(rightNode==null){//右节点为空,直接将排序结点赋值给右节点
			rightNode = new Node(arr[index++]);
		}else{
			rightNode.createNodeRecursive(arr,index);
		}
	}
	
}

第二种方式(同样也是递归)

public void createNodeRecursive(Node node){//参数列表不同,方法的重载
	if(node.data<data){
			if(leftNode==null){
				leftNode=node;
			}else{
				leftNode.createNodeRecursive(node);
			}
	}else{
		if(rightNode==null){
			rightNode=node;
		}else{
			rightNode.createNodeRecursive(node);
		}
	}

有序非递归创建二叉树

思路:我们是将LIst集合中的根节点之后的结点与创建中的二叉树结点进行比较,比他小放左边大放右边,循环的调件就是二叉树中存在左右节点,循环往下遍历。

	/*
	 * 思路 循环判断比较,从根节点开始,如果结点存在左右子节点是执行while循环,否则退出
	 * 如果刚好左节点为空此时的值刚好小于根节点的值 直接将该节点赋到左节点并退出循环
	 * 相反如果该值大于右节点此时右节点刚好为空 将该节点赋到右节点
	 * 如果左节点不为空右节点为空,此时值刚好又小于结点值,所有就要往下遍历
	 * 如果该右节点不为空左节点为空,此时值刚好又大于结点值,所有继续往下遍历
	 * 如果作用结点都不为空,则要判断该值是否大于该结点值,判断位置
	 */
public void createNode(int[] arr){
	dates= new ArrayList<Node>();//初始化集合
	for(int i=0:arr){//将arr包装进到ArrayList集合当中
		datas.add(new Node(i));
	}
	root = datas.get(0);//初始化根节点
	for(int i=1;i<arr.length;i++){//除根结之外的其他节点的排序比较创建
	Node node = root;//每次的子结点从root结点开始遍历
		while(node.leftNode!=null||node.rightNode!=null&&datas.indexOf(node)<arr.length-1){//二叉树最坏的一种情况(只存在左子树或者右子树)的结点树
		//如果左右结点不为空,列举除包含的所有情况
			if(datas.get(i)<node.data&&node.leftNode==null){
					node.leftNode=datas.get(i);
					break;
			}else if(node.data<datas.get(i).data&&node.rightNode==null){
					node.rightNode = datas.get(i);
					break;
			}else if(node.rightNode!=null&&node.leftNode==null){//不为空子结点后移
				node = node.rightNode;
			}else if(node.leftNode!=null&&node.rightNode==null){
				node = node.leftNode;
			}else if(node.leftNOde!=null&&node.rightNode!=null){//都不为空时需要判断,如果小于该节点则往左遍历,控制遍历方向
				if(datas.get(i).data<node.data){
					node = node.leftNode;
				}else{
					node = node.rightNode;
				}
			}
		}//左右结点都为空
		if(datas.get(i)<node.data){
			node.leftNode=datas.get(i);
		}else{
			node.rightNOde=datas.get(i);
		}
	}
}

中序遍历

public void inorder(Node root){
	if(root!=null){
		inorder(root.leftNode);
		System.out.print(root.data);
		inorder(root.rightNode);
	}
}

遍历结果

package node;

public class Test {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int[] arr= {7,2,8,1,4,3,5};
		Node node = new Node();
		node.createOrder(arr);
		node.inorder(node.root);
	}

}

结果:
在这里插入图片描述

以上是关于java编写非递归与递归创建有序的二叉树的主要内容,如果未能解决你的问题,请参考以下文章

Java实现二叉树的创建递归/非递归遍历

非递归的二叉树遍历

非递归的二叉树遍历

最容易理解的二叉树后续遍历非递归java实现

递归非递归的二叉树遍历(递归前中后,非递归前中后,层次遍历,凹入打印法等)

二叉树的前中后序递归和非递归遍历操作代码