赞
踩
在实际开发过程中,一些特殊的数据结构无法用普通的数据类型表示出来,我们需要将其序列化,然后在我们需要使用的时候再反序列化
二叉树节点结构:
//二叉树节点结构
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){ //如果head(节点)为null,也需要添加进去,占位 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 Node preb(Queue<String> preList){ //出队列 String value = preList.poll(); //判断弹出是否为null if(value == null){ return null; } Node head = new Node(Integer.valueOf(value)); //队列中:中左右 【出:中左右,先进先出】 head.left = preb(preList); head.right = preb(preList); return head; }
注意:树无法使用中序来进行序列化、反序列化【会产生歧义】
//后序列化【左右根】 public static Queue<String> posSerial(Node head){ Queue<String> queue = new LinkedList<>(); poss(queue, head); return queue; } public static void poss(Queue<String> queue, Node head){ //为null也需要添加:需要占位 if(head == null){ queue.add(null); return; } poss(queue, head.left); poss(queue, head.right); queue.add(String.valueOf(head.value)); }
public static Node buildByPosQueue(Queue<String> posList){ if(posList == null || posList.size() == 0){ return null; } //后序【左右根】 //利用栈结构,构建根右左 Stack<String> stack = new Stack<>(); while (!posList.isEmpty()){ stack.push(posList.poll()); } return posb(stack); } public static Node posb(Stack<String> posstack){ String value = posstack.pop(); if(value == null){ return null; } //根 右 左 Node head = new Node(Integer.parseInt(value)); head.right = posb(posstack); head.left = posb(posstack); return head; }
//层序:序列化 public static Queue<String> levelSerial(Node head){ Queue<String> ans = new LinkedList<>(); if(head == null){ ans.add(null); } else { ans.add(String.valueOf(head.value)); Queue<Node> queue = new LinkedList<>(); queue.add(head); while(!queue.isEmpty()){ //每次找到新的节点 head = queue.poll(); if(head.left != null){ //左不为null,进队列 ans.add(String.valueOf(head.left.value)); queue.add(head.left); } else { ans.add(null); } if(head.right != null){ ans.add(String.valueOf(head.right.value)); queue.add(head.right); } else { ans.add(null); } } } return ans; }
思路:
先弹出一个head,然后将head放入队列,判断head是否为null,如果不为null,从levelList中弹出左右节点,并且将其左右节点添加进queue
//层序:反序列化 public static Node buildByLevelQueue(Queue<String> levelList){ if(levelList == null || levelList.size() == 0){ return null; } //先弹出head节点 Node head = generateNode(levelList.poll()); Queue<Node> queue = new LinkedList<>(); if(head != null){ queue.add(head); } Node node = null; while(!queue.isEmpty()){ node = queue.poll(); node.left = generateNode(levelList.poll()); node.right = generateNode(levelList.poll()); if(node.left != null){ queue.add(node.left); } if(node.right != null){ queue.add(node.right); } } return head; } //构建节点 public static Node generateNode(String val){ if(val == null){ return null; } return new Node(Integer.valueOf(val)); }
思路:将所有子节点全部放在左边,兄弟节点全部放在右边
1.节点类
//N叉树节点 public static class Node { public int val; public List<Node> children; public Node() { } public Node(int val, List<Node> children) { this.val = val; this.children = children; } } //二叉树节点 public static class TreeNode { public int val; TreeNode left; TreeNode right; TreeNode(int val) { this.val = val; } }
2.编码:【将N叉树变为二叉树】
//将N叉树变为二叉树【编码】 //【左边放root的孩子,右边放root的兄弟节点】 public TreeNode encode(Node root){ if(root == null){ return null; } TreeNode head = new TreeNode(root.val); //将root的所有子孩子全部挂载到left head.left = en(root.children); return head; } //处理root的孩子 private TreeNode en(List<Node> children){ TreeNode head = null; TreeNode cur = null; for(Node child : children){ TreeNode tNode = new TreeNode(child.val); if(head == null){ head = tNode; } else { //兄弟节点 cur.right = tNode; } cur = tNode; //【分配节点的孩子】 cur.left = en(child.children); } return head; }
3.解码:【将二叉树转换为多叉树】
//解码:将二叉树变为多叉树 public Node decode(TreeNode root){ if(root == null){ return null; } return new Node(root.val, de(root.left)); } public List<Node> de(TreeNode root){ List<Node> children = new ArrayList<>(); while(root != null){ //左边存放是孩子 Node cur = new Node(root.val, de(root.left)); children.add(cur); //去找兄弟节点 root = root.right; } return children; }
给定一个root节点,返回该二叉树的最大宽度是多少
方法一:使用map
public static int maxWidthUseMap(Node head) { if (head == null) { return 0; } Queue<Node> queue = new LinkedList<>(); queue.add(head); HashMap<Node, Integer> levelMap = new HashMap<>(); //value : 第几层 levelMap.put(head, 1); //当前所在层数 int curLevel = 1; //当前层是curLevel,宽度目前是多少 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.left); } if (cur.right != null) { levelMap.put(cur.right, curNodeLevel + 1); queue.add(cur.right); } //查看是否是当前层,如果是,curLevelNodes++ if(curNodeLevel == curLevel){ curLevelNodes++; } else { max = Math.max(max, curLevelNodes); curLevel++; curLevelNodes = 1; } } max = Math.max(max, curLevelNodes); return max; }
方法二:
/** * 不使用map方法【找到当前层及下一层的最右节点】 * 核心:每层的最右节点 * * @param head * @return */ public static int maxWidthNoMap(Node head) { if (head == null) { return 0; } //队列:存放节点 Queue<Node> queue = new LinkedList<>(); //头节点不为null,将其放入queue queue.add(head); Node curNode = head;//当前层节点最右节点 Node nextEnd = null; int curLevelNodes = 0;//每层节点数 int res = 0; while (!queue.isEmpty()) { //队列弹出当前节点 Node cur = queue.poll(); if (cur.left != null) { queue.add(cur.left); //更新下一层最右节点 nextEnd = cur.left; } if (cur.right != null) { queue.add(cur.right); nextEnd = cur.right; } curLevelNodes++; res = Math.max(res, curLevelNodes); if (cur == curNode) { //当前节点为当前层的最右节点 curLevelNodes = 0; //当前层的最右节点更新 curNode = nextEnd; } } return res; }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。