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

二叉树

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;
}


相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...