class Node{
constructor(){
this.value=null;
this.left=null;
this.right=null;
}
make(Node){
this.value=Node.value;
this.left=Node.left;
this.right=Node.right;
}
}
class NodeS{
constructor(){
this.value;
this.left;
this.right;
this.father;
}
}
class JST{
constructor(){
this.isST=null;
this.max=null;
this.min=null;
}
}
class JFT{
constructor(){
this.isFT=null;
this.height=null;
this.nodeSum=null;
}
}
class JSBT{
constructor(){
this.isSB=null;
this.height=null;
}
}
//递归遍历
function RePre(head){
if(head==null){
return;
}
console.log(head.value);//先序
RePre(head.left);
//console.log(head.value);//中序
RePre(head.right);
//console.log(head.value);//后序
}
//非递归先序
function Pre(head){
let stack=new Array();
stack.unshift(head);
while(stack.length){
let tmp=stack.shift();
console.log(tmp.value);
if(tmp.right){
stack.unshift(tmp.right);
}
if(tmp.left){
stack.unshift(tmp.left);
}
}
}
//非递归后续
function Post(head){
let stack1=new Array();
let stack2=new Array();
stack1.unshift(head);
while(stack1.length){
let tmp=stack1.shift();
stack2.unshift(tmp);//放入收集栈中
if(tmp.left){
stack1.unshift(tmp.left);
}
if(tmp.right){
stack1.unshift(tmp.right);
}
}
while(stack2.length){
let tmp =stack2.shift();
console.log(tmp.value);
}
}
//非递归中序
function Med(head){
let stack=new Array();
let tmp=head.left;
stack.unshift(head);
while(tmp){
stack.unshift(tmp);//把左节点全部压入栈
tmp=tmp.left;
}
while(stack.length){
tmp=stack.shift();
console.log(tmp.value);
if(tmp.right){
tmp=tmp.right;
while(tmp){
stack.unshift(tmp);
tmp=tmp.left;
}
}
}
}
//用队列实现宽度优先搜索
function BFS(head){
let queue=new Array();
queue.push(head);
while(queue.length){
let tmp=queue.shift();
console.log(tmp.value);
if(tmp.left){
queue.push(tmp.left);
}
if(tmp.right){
queue.push(tmp.right);
}
}
}
//求树的最大宽度
//哈希表快速解决
function GetWidth(head){
let LevMap =new Map();
let max=-1;
let curlev=0;let cursum=0;
let que=new Array();
que.push(head);
LevMap.set(head,0);
while(que.length){
let tmp=que.shift();
if(LevMap.get(tmp)==curlev){
cursum++;
}
else{
max=cursum>max?cursum:max;
curlev++;
cursum=1;
}
if(tmp.left){
LevMap.set(tmp.left,curlev+1);
que.push(tmp.left);
}
if(tmp.right){
LevMap.set(tmp.right,curlev+1);
que.push(tmp.right);
}
}
console.log(max);
}
//用节点记录当前层和下一层的终点,不用哈希表以减少空间复杂度
function GetWidth2(head){
let que=new Array();
que.push(head);
let curend=head;let nextend=null;
let max=-1;let cursum=0;
while(que.length){
let tmp=que.shift();
cursum++;
if(tmp.left){
nextend=tmp.left;
que.push(tmp.left);
}
if(tmp.right){
nextend=tmp.right;
que.push(tmp.right);
}
if(tmp==curend){
curend=nextend;
max=cursum>max?cursum:max;
cursum=0;
}
}
console.log(max);
}
//搜索二叉树判断 模板递归
function SearchTree(head){
if(head==null){
let tmp=new JST();
tmp.isST=true;
return tmp;
}
let left=new JST();
left=SearchTree(head.left);
let right=new JST();
right=SearchTree(head.right);
let sign=new JST();
if(left.max!=null&&right.max!=null){//max不为空说明不为空树
let ma=left.max>right.max?left.max:right.max;
sign.max=head.value>ma?head.value:ma;
let mi=left.min<right.min?left.min:right.min;
sign.min=head.value<mi?head.value:mi;
}
else if(left.max!=null){
sign.max=head.value>left.max?head.value:left.max;
sign.min=head.value<left.min?head.value:left.min;
}
else{
sign.max=head.value>right.max?head.value:right.max;
sign.min=head.value<right.min?head.value:right.min;
}
sign.isST=true;
if(left.isST==false||right.isST==false){
sign.isST=false;
}
if(left.max!=null&&left.max>=head.value){
sign.isST=false;
}
if(right.min!=null&&right.min<=head.value){
sign.isST=false;
}
return sign;
}
//满二叉树 模板递归
function FullTree(head){
if(head==null){
let tmp=new JFT();
tmp.isFT=true;tmp.height=0;tmp.nodeSum=0;
return tmp;
}
let left=new JFT();
let right=new JFT();
left=FullTree(head.left);
right=FullTree(head.right);
let sign=new JFT();
let ma=left.height>right.height?left.height:right.height;
sign.height=ma+1;
sign.nodeSum=left.nodeSum+right.nodeSum+1;
sign.isFT=false;
if(sign.nodeSum==Math.pow(2,sign.height)-1){
sign.isFT=true;
}
return sign;
}
//平衡二叉树 模板递归
function SBTree(head){
if(head==null){//设置baseCase
let tmp=new JSBT();
tmp.isSB=true;tmp.height=0;
return tmp;
}
let left=new JSBT();//得到左右子树的返回
let right=new JSBT();
left=SBTree(head.left);
right=SBTree(head.right);
let sign=new JSBT();//给出自己的返回
let ma=left.height>right.height?left.height:right.height;
sign.height=ma+1;
sign.isSB=true;
if(left.isSB==false||right.isSB==false){
sign.isSB=false;
}
if(Math.abs(left.height-right.height)>1){
sign.isSB=false;
}
return sign;
}
//完全二叉树 BFS搞定
function CBT(head){
let que=new Array();
let isLeaf=false;
let Ret=true;
que.push(head);
while(que.length){
let tmp=que.shift();
if(tmp.left==null&&tmp.right!=null){//任一节点有右无左false
Ret=false;
break;
}
if(isLeaf==false&&(tmp.left&&tmp.right==null)){//第一次遇到左右不全时,后续都是叶节点
isLeaf=true;
}
else if(isLeaf&&(tmp.left||tmp.right)){//不是叶节点false
Ret=false;
break;
}
if(tmp.left){
que.push(tmp.left);
}
if(tmp.right){
que.push(tmp.right);
}
}
console.log(Ret);
}
//找到最低公共祖先
//哈希表
function FindLA1(head,n1,n2){
if(n1==n2){//假设给同一个节点
return n1;
}
let fathetMap=new Map();
let tmp=head;
let stack=new Array();
stack.unshift(head);
fathetMap.set(head,head);//根的节点是他自己
while(stack.length){//知道每一个节点的父亲节点
tmp=stack.shift();
if(tmp.left){
fathetMap.set(tmp.left,tmp);
stack.unshift(tmp.left);
}
if(tmp.right){
fathetMap.set(tmp.right,tmp);
stack.unshift(tmp.right);
}
}
//从n1节点往上遍历,把他和他的父亲节点都放进set里
let judgeSet=new Set();
judgeSet.add(n1);
tmp=n1;
while(1){
let tmpFather;
tmpFather=fathetMap.get(tmp);
judgeSet.add(tmpFather);
if(tmp==tmpFather){//相等说明到根节点了
break;
}
tmp=tmpFather;
}
//从n2节点往上遍历,从set里找第一个遇到的就是最低公共祖先
tmp=n2;
while(1){
let tmpFather;
tmpFather=fathetMap.get(tmp);
if(judgeSet.has(tmpFather)){
return tmpFather;
}
tmp=tmpFather;
}
}
//奇妙的递归解决,相当于把n1,n2向上传递
function FindLA2(head,n1,n2){
if(n1==n2){
return n1;
}
if(head==null){
return null;
}
let left=FindLA2(head.left,n1,n2);
let right=FindLA2(head.right,n1,n2);
if(head==n1||head==n2){
return head;
}
if(left&&right){
return head;
}
else if(left){
return left;
}
else{
return right;
}
}
//找到后继节点 判断情况
function FindFollowNode(n1){
if(n1.right){//n1有右树向下找最左节点
let tmp=n1.right;
while(tmp.left){
tmp=tmp.left;
}
return tmp;
}
let father=n1.father;
while(father){//n1无右树往上找,当前节点是其父节点的左孩子停,没找到也停
if(father.left==n1){
return father;
}
n1=father;
father=n1.father;
}
return null;
}
//先序遍历 序列化树,null值变为#
function Serial(head,arr){
if(head==null){
arr.push("#");
return;
}
arr.push(head);
Serial(head.left,arr);
Serial(head.right,arr);
return arr;
}
//先序遍历 反序列化
function DeSerial(head,arr){
head=arr.shift();
if(head=='#'){
return null;
}
DeSerial(head.left,arr);
DeSerial(head.right,arr);
return head;
}
//折纸打印凹凸痕迹
function Aotu(num){
printP(1,num,true);
}
function printP(i,num,flag){//i代表当前层数
if(i>num){
return;
}
printP(i+1,num,true);
let tmp=flag==true?'凹':'凸';
console.log(tmp);
printP(i+1,num,false);
}
//测试用树
let head2=new NodeS();
let ss1=new NodeS();
let ss2 =new NodeS();
let ss3 =new NodeS();
head2.value=1;head2.father=null;
ss1.value=2;ss2.value=3;ss3.value=4;
head2.left=ss1;ss1.father=head2;
head2.right=ss2;ss2.father=head2;
ss1.right=ss3;ss3.father=ss1;
//测试用树 普通
let head=new Node();
head.value=7;
let p1=new Node();
head.left=p1;p1.value=5;
let p2=new Node();
p1.left=p2;p2.value=3;
let p3=new Node();
p1.right=p3;p3.value=6;
let p4=new Node();
p3.left=p4;p4.value=9;
let p5=new Node();
p4.left=p5;p5.value=8;
let p6=new Node();
head.right=p6;p6.value=6;
let p7=new Node();
p6.left=p7;p7.value=1;
let p8=new Node();
p7.right=p8;p8.value=2;
let p9=new Node();
p8.left=p9;p9.value=11;
let p10=new Node();
p6.right=p10;p10.value=12;
// RePre(head);
// Pre(head);
// Post(head);
// Med(head);
// BFS(head);
// GetWidth(head);
// GetWidth2(head);
// let i=SearchTree(head);
// console.log(i.isST);
// i=SearchTree(head2);
// console.log(i.isST);
// let i=FullTree(head);
// console.log(i.isFT);
// i=FullTree(head2);
// console.log(i.isFT);
// let i=SBTree(head);
// console.log(i.isSB);
// i=SBTree(head2);
// console.log(i.isSB);
// CBT(head2);
// let tmp=FindLA2(head,p2,p10);
// console.log(tmp.value);
// let tmp=FindFollowNode(ss1);
// if(tmp)
// console.log(tmp.value);
// else
// console.log("null");
// let head3;
// let arr=new Array();
// arr=Serial(head,arr);
// head3=DeSerial(head3,arr);
// Post(head3);
// for(let i in arr){
// console.log(arr[i]);
// }
Aotu(2);