《剑指offer》– 二叉树的下一个结点、对称二叉树、按之字性顺序打印二叉树、把二叉树打印成多行

《剑指offer》– 二叉树的下一个结点、对称二叉树、按之字性顺序打印二叉树、把二叉树打印成多行

一、二叉树的下一个结点:

1、题目:

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

2、解题思路:

分析二叉树的下一个节点,一共有以下情况:
(1)二叉树为空,则返回空;
(2)节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
(3)节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复第三步的判断,返回结果。

3、代码实现:

public class Test15 {
	
	 public TreeLinkNode GetNext(TreeLinkNode pNode){
		 
		 if(pNode == null){
			 return null;
		 }
		 if(pNode.right != null){
			 pNode = pNode.right;
			 while(pNode.left!=null){
				 pNode = pNode.left;
			 }
			 return pNode;
		 }
		 while(pNode.next!=null){
			 TreeLinkNode parent = pNode.next;
			 if(parent.left==pNode){
				 return parent;
			 }
			 pNode = pNode.next;
		 }
		 return null;
    }
}

class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;//指向改节点的父节点
    TreeLinkNode(int val) {
        this.val = val;
    }
}

 

二、对称二叉树:

1、题目:

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

2、解题思路:

最简单的方式可以使用递归方式,但是使用递归无法挖掘这道题的价值,因此我们可以使用DFS和BFS。

3、代码实现:

(1)第一种:递归算法:

①只要pRoot.left和pRoot.right是否对称即可。

②左右节点的值相等且对称子树left.left,right.right ;left.rigth,right.left也对称。

public class Test16 {

	boolean isSymmetrical(TreeNode pRoot){
		if(pRoot == null) return true;
		return judge(pRoot.left,pRoot.right);
    }
	
	boolean judge(TreeNode leftNode,TreeNode rightNode){
		if(leftNode == null) return rightNode==null;
		if(rightNode == null) return false;
		if(leftNode.val != rightNode.val) return false;
		return judge(leftNode.left,rightNode.right) && judge(leftNode.right,rightNode.left);
	}
	
}

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;

    }
}

(2)第二种方法:DFS深度优先遍历:

DFS使用stack来保存成对的节点,

①出栈的时候也是成对成对的:

若都为空,继续;

一个为空,返回false;

不为空,比较当前值,值不等,返回false;

②确定入栈顺序,每次入栈都是成对成对的,如left.left,right.right ;left.rigth,right.left

	boolean isSymmetrical2(TreeNode pRoot){
		//第二种方法:使用深度遍历:利用Stack实现
		if(pRoot==null) return true;
		
		Stack<TreeNode> stack = new Stack<>();
		//入栈和出栈都需要成对
		stack.push(pRoot.left);
		stack.push(pRoot.right);
		while(!stack.isEmpty()){
			//成对取出
			TreeNode right = stack.pop();
			TreeNode left = stack.pop();
			if(left==null && right==null) continue;
			if(left==null ||right==null) return false;
			if(left.val!=right.val) return false;
			
			//成对入栈:
			stack.push(left.left);
			stack.push(right.right);
			stack.push(right.left);
			stack.push(left.right);
		}
		return true;
	}

(3)第三种方法:BFS广度优先遍历:

BFS使用Queue来保存成对的节点,代码和上面极其相似

①出队的时候也是成对成对的 

若都为空,继续;

一个为空,返回false;

不为空,比较当前值,值不等,返回false;

②确定入队顺序,每次入队都是成对成对的,如left.left,right.right ;left.rigth,right.left。

	boolean isSymmetrical3(TreeNode pRoot){
		//第三种方法:使用广度遍历:使用队列实现
		if(pRoot==null) return true;
		Queue<TreeNode> queue = new LinkedList<>();
		
		queue.offer(pRoot.left);
		queue.offer(pRoot.right);
		
		while(!queue.isEmpty()){
			//成对取出
			TreeNode right = queue.poll();
			TreeNode left = queue.poll();
			
			if(left ==null && right ==null) continue;
			if(left==null || right==null) return false;
			if(left.val != right.val) return false;
			
			//成对插入
			queue.offer(left.left);
			queue.offer(right.right);
			queue.offer(left.right);
			queue.offer(right.left);
		}
		return true;
	}

 

三、按之字性顺序打印二叉树:

1、题目:

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

2、解题思路:

利用栈先进后出的性质,创建两个栈分别存放奇数层与偶数层的节点。

3、代码实现:

public class Test18 {
	public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
		int layer = 1;
		//s1存奇数层节点:
		Stack<TreeNode> s1 = new Stack<TreeNode>();
		s1.push(pRoot);
		//s2存放偶数层节点:
		Stack<TreeNode> s2 = new Stack<TreeNode>();
		ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
		
		while(!s1.empty() || !s2.empty()){
			if(layer%2 !=0){
				//奇数层:
				ArrayList<Integer> temp = new ArrayList<Integer>();
				while(!s1.empty()){
					TreeNode node = s1.pop();
					if(node!=null){
						temp.add(node.val);
						s2.push(node.left);
						s2.push(node.right);
					}
				}
				if(!temp.isEmpty()){
					list.add(temp);
					layer++;
				}
			}else{
				//偶数层:
				ArrayList<Integer> temp = new ArrayList<Integer>();
				while(!s2.isEmpty()){
					TreeNode node = s2.pop();
					if(node!=null){
						temp.add(node.val);
						s1.push(node.right);
						s1.push(node.left);
					}
				}
				if(!temp.isEmpty()){
					list.add(temp);
					layer++;
				}
			}
		}
		return list;
    }
}

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}

 

四、把二叉树打印成多行:

1、题目:

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

2、代码实现:

public class Test19 {
	
	 ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
		 ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
		 if(pRoot == null){
			 return result;
		 }
		 
		 Queue<TreeNode> queue = new LinkedList<TreeNode>();
		 ArrayList<Integer> queueList = new ArrayList<Integer>();
		 queue.add(pRoot);
		 int start = 0 ,end = 1;

		 while(!queue.isEmpty()){
			 TreeNode current = queue.remove();
			 queueList.add(current.val);
			 start++;
			 if(current.left!=null){
				 queue.add(current.left);
			 }
			 if(current.right!=null){
				 queue.add(current.right);
			 }
			 if(start == end){
				 end = queue.size();
				 start=0;
				 result.add(queueList);
				 queueList = new ArrayList<Integer>();
			 }
			 
		 }
		 return result;
    }
}

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114693.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 软件使用&vmware虚拟机的安装步骤详细[通俗易懂]

    实验环境:Windows+Vmware12+RHEL7.2+Xshell5准备工作:1.关闭并退出360,电脑管家等优化软件,防止虚拟机运行出现问题。2.打开链接http://www.vmware.com/cn/products/workstation/workstation-evaluation下载试用版3.安装该软件,可以指定将来虚拟机存放的目录,其他随意。打开vmwar…

  • UNIX的常用命令「建议收藏」

    UNIX的常用命令「建议收藏」Unix常用命令介绍:  多命令行:“;”多行命令:“\”1、系统关闭reboot、halt/shutdown、poweroff2、passwd命令:修改系统用户密码passwd[username]3、su命令:切换系统用户su[-username]username为空表示root用户4、cat命令:将指定的文件在标准输出到显示器cat [-AbET] [文件名列表]-A      …

  • vue 修改引入组件的样式_vue子组件的子组件布局

    vue 修改引入组件的样式_vue子组件的子组件布局意义vue被广大前端推崇很重要一点就是组件封装,但是在组件封装的时候,组件可能在各处都要用到,但是在各处的样式可能不太一样,例如:按钮组件,这时怎么办,难道不同样式但是结构相同的组件进行多次封装么?很明显是很不合算的。用代码说话父组件:<template><el-containerclass=”layout_container”><el-headerheight=”auto”><header-top></header-top&

  • 如何高效学习PLC

    如何高效学习PLC【1】电工原理和电机原理一定要懂,简单的就记背也要背下来,比如马达容量1KW2A,正反转,星三角接线,电线容量。电阻,电感,电容的特性等;【2】液压和气动也要掌握,比如压力换算,压力和电流的比例换算,这在有压力控制上都要用到;【3】电线截面要会看,线拿到手就知道几平方的,还有什么电器上该用什么线,比如马达就用4线的,3根主线1根接地。从变频器上出来的要用屏蔽线;【4】机修也要会做,特别是螺丝…

    2022年10月19日
  • Vue框架快速入门

    Vue框架快速入门Vue是现在最流行的前端框架之一,而且相对于其他两个框架React和Angular来说也更加易学,而且它的作者是国人,中文文档也很完善。当然Vue框架算是比较高级的框架,所以在使用过程中还需要JavaScript、JavaScript2015、WebPack、NodeJS、npm、ESLint、JavaScript单元测试框架等其他知识和框架的使用方法。在学习Vue之前,最好先学习一下这些知识。由

  • 分层应用——怎样实现登录?

    分层应用——怎样实现登录?

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号