java数据结构与算法(八)——树

一、二叉树

package Tree;

public class BinaryTreeDemo {

	public static void main(String[] args) {

		//现需要创建一棵二叉树
		binaryTree binarytree = new binaryTree();
		
		//创建需要的节点
		HeroNode root = new HeroNode(1, "宋江");
		HeroNode node2 = new HeroNode(2, "吴用");
		HeroNode node3 = new HeroNode(3, "卢俊义");
		HeroNode node4 = new HeroNode(4, "林冲");
		HeroNode node5 = new HeroNode(5, "关胜");
		
		//手动创建二叉树
		root.setLeft(node2);
		root.setRight(node3);
		node3.setRight(node4);
		node3.setLeft(node5);
		binarytree.setRoot(root);
		
		//前序遍历
		System.out.println("前序遍历");
		binarytree.preOrder();
		
		//中序遍历
		System.out.println("中序遍历");
		binarytree.infixOrder();
		
		
		//后序遍历
		System.out.println("后序遍历");
		binarytree.postOrder();
		
		HeroNode res = null;
		//前序遍历查找
		res = binarytree.preOrderSearch(5);
		if (res != null) {
			System.out.println(res);
		}else {
			System.out.println("没有找到");
		}
		
		
		HeroNode res1 = null;
		// 中序遍历查找
		res1 = binarytree.infixOrderSearch(5);
		if (res1 != null) {
			System.out.println(res1);
		}else {
			System.out.println("没有找到");
		}
		
		HeroNode res2 = null;
		// 后序遍历查找
		res2 = binarytree.postOrderSearch(5);
		if (res2 != null) {
			System.out.println(res2);
		}else {
			System.out.println("没有找到");
		}
		
		//删除节点
		binarytree.delNode(4);
		System.out.println("删除节点后:");
		binarytree.postOrder();
		

	}

}


//定义BinaryTree,二叉树
class binaryTree{
	
	private HeroNode root; //根节点

	public void setRoot(HeroNode root) {
		this.root = root;
	}
	
	//前序遍历
	public void preOrder() {
		if (this.root != null) {
			this.root.preOrder1(); 
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	
	//中序遍历
	public void infixOrder() {
		if (this.root != null) {
			this.root.infixOrder(); //为什么调用的是heronode中的方法而不是递归? 
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	
	//后序遍历
	public void postOrder() {
		if (this.root != null) {
			this.root.postOrder();
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	
	//前序遍历查找
	public HeroNode preOrderSearch(int no) {
		if (root != null) {
			return root.preOrderSearch(no);
		}else {
			return null;
		}
	}
	
	//中序遍历查找
	public HeroNode infixOrderSearch(int no) {
		if (root != null) {
			return root.infixOrderSearch(no);
		}else {
			return null;
		}
	}
	
	//后序遍历查找
	public HeroNode postOrderSearch(int no) {
		if (root != null) {
			return root.postOrderSearch(no);
		}else {
			return null;
		}
	}
	
	//删除节点
	public void delNode(int no) {
		//先判断根节点是否为空,是否等于要删除的节点,如果是就将其删除
		if (root != null) {
			if (root.getNo() == no) {
				root = null;
			}else {
				root.delNode(no);
			}
			
		}else {
			System.out.println("空树,不能删除");
		}
	}
	
	
}




//先创建HeroNode节点
class HeroNode{
	private int no;
	private String name;
	private HeroNode left; //遍历左节点的指针
	private HeroNode right;
	
	//构造器
	public HeroNode(int no, String name){
		this.no = no;
		this.name = name;
	}

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public HeroNode getLeft() {
		return left;
	}

	public void setLeft(HeroNode left) {
		this.left = left;
	}

	public HeroNode getRight() {
		return right;
	}

	public void setRight(HeroNode right) {
		this.right = right;
	}

	//重写toString方法
	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + "]";
	}
	
	//前序遍历方法
	public void preOrder1() {
		
		System.out.println(this); //先输出当前节点(父节点),打印对象的toString方法
		
		//向左子树进行递归遍历
		if (this.left != null) {
			//若果左子树不为空,则遍历
			this.left.preOrder1();
		}
		
		//向右子树进行递归遍历
		if (this.right != null) {
		//若果右子树不为空,则遍历
		this.right.preOrder1();
	    }
	}
	
	//中序遍历方法
	public void infixOrder() {
	
		// 向左子树进行递归遍历
		if (this.left != null) {
			//若果左子树不为空,则遍历
			this.left.infixOrder();
		}
		
		//输出父节点
		System.out.println(this);
		
		// 向右子树进行递归遍历
		if (this.right != null) {
			// 若果右子树不为空,则遍历
			this.right.infixOrder();
		}
	
	}

	//后序遍历方法
	public void postOrder() {
		
		// 向左子树进行递归遍历
		if (this.left != null) {
			//若果左子树不为空,则遍历
			this.left.postOrder();
		}
		
		// 向右子树进行递归遍历
		if (this.right != null) {
			// 若果右子树不为空,则遍历
			this.right.postOrder();
		}

		// 输出父节点
		System.out.println(this);
		
	}
	
	
	//前序遍历查找
	public HeroNode preOrderSearch(int no) {
		//判断当前节点是否等于要查找的节点
		System.out.println("前序遍历查找");
		if (this.no == no) {
			return this; //return返回方法指定的类型值,return后面的语句不会执行
		}
		
		//如果当前节点不是要查找的节点,遍历左节点
		//先判断左节点是否为空,如果不判断,递归的时候会陷入空指针异常
		//创建一个临时节点用于存放找到的节点
		HeroNode resNode = null;
		if (this.left != null) {
			resNode = this.left.preOrderSearch(no);
		}
		if (resNode != null) {
			return resNode;
		}
		
		//如果左递归节点没有找到就递归有节点
		if (this.right != null) {
			resNode = this.right.preOrderSearch(no);
		}
		return resNode;
	}
	
	
	//中序遍历查找
	public HeroNode infixOrderSearch(int no) {

		//先判断左节点是否为空,如果不判断,递归的时候会陷入空指针异常
		//创建一个临时节点用于存放找到的节点
		HeroNode resNode = null;
		if (this.left != null) {
			resNode = this.left.infixOrderSearch(no);
		}
		if (resNode != null) {
			return resNode;
		}
		
		//判断当前节点是否等于要查找的节点
		System.out.println("中序遍历查找");
		if (this.no == no) {
			return this; //return返回方法指定的类型值,return后面的语句不会执行
		}
		
		
		//如果左递归节点没有找到就递归右节点
		if (this.right != null) {
			resNode = this.right.infixOrderSearch(no);
		}
		return resNode;
	}
	
	
	//后序遍历查找
	public HeroNode postOrderSearch(int no) {

		//先判断左节点是否为空,如果不判断,递归的时候会陷入空指针异常
		//创建一个临时节点用于存放找到的节点
		HeroNode resNode = null;
		if (this.left != null) {
			resNode = this.left.postOrderSearch(no);
		}
		if (resNode != null) {
			return resNode;
		}
		
		// 如果左递归节点没有找到就递归右节点
		if (this.right != null) {
			resNode = this.right.postOrderSearch(no);
		}
		if (resNode != null) {
			return resNode;
		}
		
		//判断当前节点是否等于要查找的节点
		System.out.println("后序遍历查找");
		if (this.no == no) {
			return this; //return返回方法指定的类型值,return后面的语句不会执行
		}
		
		return resNode;
		
		
		
	}
	
	
	//删除节点
	public void delNode(int no) {
		//先判断当前节点的左子节点和右子节点,不能去判断当前节点
		if (this.left != null && this.left.no == no) {
			this.left = null;
			return;
		}
		
		if (this.right != null && this.right.no == no) {
			this.right = null;
			return;
		}
		
		//若果当前节点的左子节点和右子节点都不是,就需要先对左子节点进行递归
		if (this.left != null) {
			this.left.delNode(no);
		}
		
		//如果左子节点递归没有找到,就对右子节点进行递归查找
		if (this.right != null) {
			this.right.delNode(no);
		}
		
	}
		
	
}

二、顺序存储二叉树

package Tree;

public class ArrayTreeBinaryDemo {

	public static void main(String[] args) {
		int[] arr = { 1, 2, 3, 4, 5, 6, 7 };

		arrayTreeBinary arraytreebinary = new arrayTreeBinary(arr);
		arraytreebinary.preOder();
	}

}


//创建顺序存储二叉树
class arrayTreeBinary{
	
	//先创建用于存储二叉树的数组
	private int[] arr;

	//构造器,将数组传进来
	public arrayTreeBinary(int[] arr) {
		this.arr = arr;
	}
	
	//重写preOrder方法,不用再用下面的方法还要传参数0进去
	public void preOder() {
		this.preOrder(0);
	}
	
	
	
	//前序遍历
	//index是数组的下标,从0开始
	public void preOrder(int index) {
		
		//先判断数组是否为空,或者数组的长度是否为0
		if (arr == null || arr.length == 0) {
			System.out.println("数组为空,不能遍历");
		}else {
			//先输出当前节点,因为二叉树数据存储在数组中,所以直接输出当前下标中的数
			System.out.println(arr[index]);
			
			//向左递归遍历
			if ((2 * index + 1) < arr.length) { //保证左节点下标不越界
				preOrder(2 * index + 1);
			}
			
			//向右递归遍历
			if ((2 * index + 2) < arr.length) { //保证左节点下标不越界
				preOrder(2 * index + 2);
			}
			
			
		}
		
	}

	
}

三、线索化二叉树

package Tree.TreadedBinaryTree;

public class TreadedBinaryTreeDemo {

	public static void main(String[] args) {
		HeroNode root = new HeroNode(1, "tom");
		HeroNode node2 = new HeroNode(3, "tom3");
		HeroNode node3 = new HeroNode(6, "tom6");
		HeroNode node4 = new HeroNode(8, "tom8");
		HeroNode node5 = new HeroNode(10, "tom10");
		HeroNode node6 = new HeroNode(14, "tom14");


		//手动创建二叉树
		root.setLeft(node2);
		root.setRight(node3);
		node2.setLeft(node4);
		node2.setRight(node5);
		node3.setLeft(node6);
		
		//线索化二叉树
		threadBinaryTree threadBinaryTree = new threadBinaryTree();
		threadBinaryTree.setRoot(root);
		threadBinaryTree.ThreadedBinaryTree();
		
		HeroNode left = node4.getLeft();
		HeroNode right = node4.getRight();
		System.out.println("10号节点的前驱结点:" + left);
		System.out.println("10号节点的后继结点:" + right);
		
		//遍历线索化二叉树
		threadBinaryTree.infixThreadedBinaryTreeList();
	}

}



//中序线索化二叉树
class threadBinaryTree{
	
	private HeroNode root; //根节点
	private HeroNode pre = null; //指向前驱结点的引用(指针),线索化的重要节点,当前节点后移后,需要将其指向当前节点

	public void setRoot(HeroNode root) {
		this.root = root;
	}
	
	//重载中序线索化二叉树
	public void ThreadedBinaryTree(){
		
		this.ThreadedBinaryTree(root);
	}
	
	// 中序线索化二叉树
	// 线索化二叉树要将二叉树的叶子节点线索化,所以要传进来需要线索化的节点
	public void ThreadedBinaryTree(HeroNode node) {
		// 传进来节点后先判断节点是否为空,否则后面遍历会报错空指针异常
		if (node == null) {
			return;
		}
		
		// 1.先进入左子节点进行递归遍历,线索化左子树

		ThreadedBinaryTree(node.getLeft());

		//2.对当前节点进行线索化
		//先判断当前节点的左子节点(前驱结点)是否为空,如果为空,说明当前节点是叶子节点,其左指针没有被利用,将当前节点指向其前驱节点
		//其前驱结点就是上一个指向他的节点
		if (node.getLeft() == null) {
			node.setLeft(pre);
			//另外还要将其左指针类型改为指向前驱节点的类型
			node.setLeftType(1);
		}
		//处理后继节点
		if (pre != null && pre.getRight() == null) {
			//让前驱结点的右指针指向当前节点
			pre.setRight(node);
			pre.setRightType(1);
		}
		//pre指向的是当前节点的前驱结点,所以当node后移后要将pre指向之前的node
		pre = node;
		
		
		
		//3.进入右子节点进行递归遍历,线索化右子树

		ThreadedBinaryTree(node.getRight());

	}
	
	
	//中序遍历中序线索化二叉树
	public void infixThreadedBinaryTreeList() {
		//先初始化一个变量,存放当前的节点,从root开始
		HeroNode node = root;
		//node不为空才能开始遍历
		while (node != null) {
			//循环找到leftType==1的节点,因为leftType==1说明该节点是叶子结点,是按照线索化处理后的节点
			while (node.getLeftType() == 0) {
				node = node.getLeft(); //找到leftType==1的节点,第一个就是数组第一个节点8
			}
			//打印leftType==1的节点
			System.out.println(node);
			
			//如果当前节点的右指针指向的是后继节点就一直输出
			while (node.getRightType() == 1) {
				node = node.getRight();
				System.out.println(node);
			}
			//如果遇到右指针指向的是右子叶,就将node节点换成右子叶,然后继续按前面的步骤查找
			node = node.getRight();
		}
	}
		
}




//先创建HeroNode节点
class HeroNode{
	private int no;
	private String name;
	private HeroNode left; //遍历左节点的指针
	private HeroNode right;
	
	//定义两个新的属性
	private int leftType; //若果leftType == 0;说明指向的是左子树,如果leftType == 1;说明指向的是前续节点
	private int rightType; //若果rightType == 0;说明指向的是右子树,如果rightType == 1;说明指向的是后继节点
	
	//因为这两个属性是私有的,所以创建两个方法可以让其他类调用这两个属性
	public int getLeftType() {
		return leftType;
	}

	public void setLeftType(int leftType) {
		this.leftType = leftType;
	}

	public int getRightType() {
		return rightType;
	}

	public void setRightType(int rightType) {
		this.rightType = rightType;
	}

	
	//构造器,创建heronode节点的实例时需要传进来no和name
	public HeroNode(int no, String name){
		this.no = no;
		this.name = name;
	}

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public HeroNode getLeft() {
		return left;
	}

	public void setLeft(HeroNode left) {
		this.left = left;
	}

	public HeroNode getRight() {
		return right;
	}

	public void setRight(HeroNode right) {
		this.right = right;
	}

	//重写toString方法
	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + "]";
	}
	
		
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值