二叉树
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);
}
}
}
}
要求要按层打印 而且还要判断出每一层的最大宽度 每层最有多少个节点
(可以判断出一层的开始 或者一层的结束)
- 方法一 用层数进行判断 是否需要结算 当前统计的节点数
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;
}
}
- 方法二 用每一层的最右节点 来进行结算 当前层的统计节点数
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 举报,一经查实,本站将立刻删除。