二叉树基本的算法简介集合

二叉树

Class Node{
	V value;
	Node left;
	Node right;
}

递归序
二叉树 先序 中序 后序遍历

// 先序打印所有节点

public static void pre(Node head){
	if(head ==null){
		return; 
	}
	System.out.println(head.value);
	pre(head.left);
	pre(head.right);
}

迭代实现 头节点 左节点 右节点
非递归(栈实现)

  • 弹出就打印节点
  • 如果有右孩子就压入右
  • 如果有左孩子就压入左

栈是先进后出 所以优先处理 左孩子

public static void pre(Node head){
	System.out.print("pre-order");
	if(head != null){
		Stack<Node> stack = new Stack<Node>();
		stack.add(head);
		while(!stack.isEmpty()){
			head=stack.pop();
			System.out.print(head.value +" ");
			if(head.right !=null){
				stack.push(head.right);
			}
			if(head.lfet != null){
				stack.push(head.left);
			}
		}
	}
	System.out.println();
}

中序遍历 先 左 头 右

public static void in(Node head){
	System.out.print("in- order: "");
	if(head != null){
		Stack<Node> stack = new Stack<Node>();
		while(! stack .isEmpty() || head!= null){  // 保证节点不为空
			if(head != null){
				stack.push(head);
				head=head.left;
			}else {   // 一直到左最子树的最左节点
				head= stack.pop();
				System.out.print(head.value+ " ");
				head = head.right;
			}
		}
	}
		System.out.println();
}

public static void in(Node head){
	if(head == null){
		return ;
	}
	in(head.left);
	System.out.printfln(head.value);
	in(head.right);
}

后序打印
迭代实现 头节点 右节点 左节点

非递归(栈实现)

  • 弹出就打印节点
  • 如果有左孩子就压入左
  • 如果有右孩子就压入右

栈是后见先出 所以优先处理 右孩子 其逆序实现了 后序
在头右左 这个栈中 在打印的时候 不进行打印 重新压入一个栈
结束后 在进行打印

public static void pos1(Node head){
	System.out.print("pos-order: ");
	if(head !=null){
		Stack<Node> s1 = new Stack<Node>();
		Stack<Node> s2 = new Stack<Node>();
		s1.push(head);
	while(s1.isEmpty()){
		head = s1.pop();
		s2.push(head);
		if(head.left != null){
			s1.push(head.lfet);
		}
		if(head.right !=null){
			s2.push(head.right);
		}
	}
	while(s2.isEmpty()){
		System.out.print(s2.pop().value+" ");
	}
      }
	System.out.println();
}

一个栈 实现后序遍历
h的变化 c的变化 栈的变化

public static void pos(Node h){
	System.out.print("pos-order: ");
	if(h != null){
		Stack<Node> stack = new Stack<Node>();
		stack.push(h);
		Node c=null;
		while(! stack.isEmpty()){
			c = stack .peek();
			if(c.left != null && h != c.left && h != c.right){
				stack.push(c.left);
			} esle if(c.right != null && h != c.right){
				stack.push(c.right);
			} else {
				System.out.print(stack.pop().value+' ');   // 打印栈栈顶的节点
		// 用 h 进行标记当前树中左子树一或者右子树是否访问过
				h=c;    //  h在跟踪上次打印的数字
			}
		}
	}
	System.out.println();
}

二叉树的宽度遍历 (层序遍历) 用队列


public static void lavel(Node head){
	if(head == null){
		return ;
	}
	Queue <Node> queue = new LinkedList();
	while(! queue .isEmpty()){
		Node cur =queue.poll;
		System.out.print(cur.value){
		if(cur.left != value)
			queue.add(cur.left);
		if(cur.right != null){
			queue.add(cur.right);
		}
	}
	}
}

要求要按层打印 而且还要判断出每一层的最大宽度 每层最有多少个节点
(可以判断出一层的开始 或者一层的结束)

  1. 方法一 用层数进行判断 是否需要结算 当前统计的节点数
public class TreeMaxWidth{
	public static class Node{
		public int value;
		public Node left;
		public Node right;
		
		public Node(int data){
			this.value=data;
		}
	}
	public static maxWidthUseMap(Node head){
		if(head == null){
			return 0;
		}
	Queue<Node> queue = new LinkedList<>();
	queue.add(head);
	//  key  在那一层  value
	HashMap<Node , Integer> levelMap = new HashMapM<>();
	levelMap.put(head,1);

	int curLevel=1;  // 当前正在统计那一层的宽度
	int curLevelNodes=0; // 当前层的宽度
	int max=0;   // 整颗树 目前为止 最大宽度
	while(! queue.isEmpty()){
		Node cur = queue.poll();
		int curNodeLevel = levelMap.get(cur);  // 当前节点的层数
		if(cur.left ! = null){
			levelMap.put(cur.left , curNodeLevel+1);  // 标记当前节点的左孩子  以及层数
			queue.add(cur.lfet);
		}
		if(cur.right ! = null){
			levelMap.put(cur.right, curNodeLevel+1);
			queue.add(cur.right);
		}
		if(curNodeLevel == curLevel){
			curLevelNodes++;
		}else{
			max=Math.max(max,curLevelNodes);
			curLevel++;               //更新当前层
			curLevelNodes =1;  // 此处当新层弹出的第一个节点  所以加加
		}    
	}
	max= Math.max(max, curLevelNdoes);  //需要在更新一次,最后一次没有新的层 去更新和结算max
	return max;
	}

}
  1. 方法二 用每一层的最右节点 来进行结算 当前层的统计节点数
public static maxWidthNoMap(Node head){
	if(head == null)
		return 0;
	Queue<Node> queue = new LinkedList<>();
	queue.add(head);
	Node curEnd = head;   //  当前层最后一个节点(当前层的最右边的节点)
	Node nnextEnd = null; //  下一层最右边节点
	int max=0;
	int curLevelNodes = 0;  //  当前层的节点数
	while(! queue.isEmpty()){
		Node cur = queue.poll();
		if(cur.lfet != null){
			queue.add(cur.left);	
			nextEnd=cur.left;
		}
		if(cur.right ! =null){
			queue.add(cur.right);
			nextEnd = cur.right;
		}
		curLevelNodes++;
		if(cur == curEnd){ // 判断当前 节点是否是本层的最右边节点
			max = Math.max(max, curLeveNOdes);
			curLevelNodes =0;
			curEnd = nextEnd;
		}
	}
}


二叉树的序列化 和 反序列
(将树 线性的保存起来) 通过字符串 或者 数组 可以彻底还原成为一个树

在数组中记录这个数组的所有节点 包括空节点
序列化和结构 一一对应

public static class Node {   //  树的结构 建立
	public int value;
	public Node left;
	public Node right;

	public Node(int data){
		this.value =data;
	}
}

public static Queue <String> PreSerial(Node head){
	Queue<String> ans = new LinkedList<>();
	pres(head,ans);
	return ans;
}


//  先序 序列化  将节点存入队列中
public static void pres(Node head, Queue<String> ans){
	if(head == null){  //  空节点也加入
		ans.add(null);
	}else {
		ans.add(String.valueOf(head.value));  // 将节点 变成字符串 放入队列中
		pres(head.left, ans); 
		pres(head.right, ans);
	}
}

public static Node buildByPreQueue (Queue<String> prelist){
	if( prelist == null  || prelist.size() ==0){
		return null;
	}
	return preb(prelist);    // 先序 方式  利用队列 建立 正棵树
}

public static preb(Queue<String> prelist){
	String value = prelist.poll();
	if(value == null)
		return null;
	Node head  = new Node(Integer.valueOf(value)); //  转换为整型 
	head.left = preb(prelist);
	head.right=preb(prelist);
	return head;
}


原文地址:https://blog.csdn.net/acwing/article/details/123577080

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

相关推荐


这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于nodejs...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs怎么实现目录不存在自动创建”文章能帮助大...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs如何实现定时删除文件”文章能帮助大家解决疑惑...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文...
本篇内容主要讲解“怎么安装Node.js的旧版本”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎...
这篇“node中的Express框架怎么安装使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要介绍“nodejs如何实现搜索引擎”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs如何实现搜索引擎...
这篇文章主要介绍“nodejs中间层如何设置”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs中间层如何设置”文...
这篇文章主要介绍“nodejs多线程怎么实现”,在日常操作中,相信很多人在nodejs多线程怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
这篇文章主要讲解了“nodejs怎么分布式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs怎么分布式”...
本篇内容介绍了“nodejs字符串怎么转换为数组”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情...
这篇文章主要介绍了nodejs如何运行在php服务器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇nodejs如何运行在php服务器文章都...
本篇内容主要讲解“nodejs单线程如何处理事件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“nodejs单线程如何...
这篇文章主要介绍“nodejs怎么安装ws模块”,在日常操作中,相信很多人在nodejs怎么安装ws模块问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
本篇内容介绍了“怎么打包nodejs代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!
本文小编为大家详细介绍“nodejs接收到的汉字乱码怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs接收到的汉字乱码怎么解决”文章能帮助大家解...
这篇“nodejs怎么同步删除文件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇...
今天小编给大家分享一下nodejs怎么设置淘宝镜像的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希