图、二叉树其他算法

图的最小生成树问题

希望将所有村庄联通,花费最小

树:有向无环图

普利姆算法——加点法

克鲁斯卡尔算法——加边法

普利姆算法

  1. 选一个点作为起点
  2. 找到以当前选中点为起点路径最短的边
  3. 如果这个边的另一端没有被联通起来,那么就联结
  4. 如果这个边的另一端也早就被连进来了,则看倒数第二短的边
  5. 重复2-4直到所有的点都联通为止

克鲁斯卡尔算法

  1. 选择最短的边进行连接
  2. 要保证边连接的两端至少有一个点是新的要点
  3. 或者这个边是将两个部落进行连接的
  4. 重复1-3直到将所有的点都连接到一起

代码实现

表示一个图,可以使用点集合和边集合

点集合:[a,b,c,d,e,f]

ABCDE
A047maxmax
B4086max
C7805max
Dmax6507
Emaxmax70
var max = 1000000;
var pointSet = [];
var distance = [
  [0, 4, 7, max, max],
  [4, 0, 8, 6, max],
  [7, 8, 0, 5, max],
  [max, 6, 5, 0, 7],
  [max, max, max, 7, 0]
];

function Node(value) {
  this.value = value;
  this.neighbor = [];
}

var a = new Node("A");
var b = new Node("B");
var c = new Node("C");
var d = new Node("D");
var e = new Node("E");

pointSet.push(a);
pointSet.push(b);
pointSet.push(c);
pointSet.push(d);
pointSet.push(e);


function getIndex(str) {
  for (var i = 0; i < pointSet.length; i++) {
    if (str == pointSet[i].value) return i;
  }
  return -1;
}

//需要传入点的集合,边的集合,当前已经连接进入的集合
// 此方法,根据当前已经有的节点,来进行判断,获取到距离最短的点
function getMinDisNode(pointSet, distance, nowPointSet) {
  var fromNode = null;//线段的起点
  var minDisNode = null;//线段的终点
  var minDis = max;
  //根据当前已有的这些点为起点,依次判断连接其他的点的距离是多少
  for (var i = 0; i < nowPointSet.length; i++) {
    var nowPointIndex = getIndex(nowPointSet[i].value);//获取当前节点的序号
    for (var j = 0; j < distance[nowPointIndex].length; j++) {
      var thisNode = pointSet[j];//thisNode表示distance中的点,但是这个点不是对象。
      if (nowPointSet.indexOf(thisNode) < 0//首先这个点不能是已经接入的点
          && distance[nowPointIndex][j] < minDis) {//其次点之间的距离得是目前的最短距离
        fromNode = nowPointSet[i];
        minDisNode = thisNode;
        minDis = distance[nowPointIndex][j];
      }
    }
  }
  fromNode.neighbor.push(minDisNode);
  minDisNode.neighbor.push(fromNode);
  return minDisNode;
}

function prim(pointSet, distance, start) {
  var nowPointSet = [];
  nowPointSet.push(start);
  //获取最小代价的边
  while (true) {
    var minDisNode = getMinDisNode(pointSet, distance, nowPointSet);
    nowPointSet.push(minDisNode);
    if (nowPointSet.length == pointSet.length) {
      break;
    }
  }
}

prim(pointSet, distance, pointSet[2]);

console.log(pointSet);

var max = 1000000;
var pointSet = [];
var distance = [
  [0, 4, 7, max, max],
  [4, 0, 8, 6, max],
  [7, 8, 0, 5, max],
  [max, 6, 5, 0, 7],
  [max, max, max, 7, 0]
];

function Node(value) {
  this.value = value;
  this.neighbor = [];
}

var a = new Node("A");
var b = new Node("B");
var c = new Node("C");
var d = new Node("D");
var e = new Node("E");

pointSet.push(a);
pointSet.push(b);
pointSet.push(c);
pointSet.push(d);
pointSet.push(e);

function canLink(resultList, tempBegin, tempEnd) {
  var beginIn = null;
  var endIn = null;
  for (var i = 0; i < resultList.length; i++) {
    if (resultList[i].indexOf(tempBegin) > -1) {
      beginIn = resultList[i];
    }
    if (resultList[i].indexOf(tempEnd) > -1) {
      endIn = resultList[i];
    }
  }
  //两个点都是新的点(都不在任何部落里)——可以连接,产生新的部落
  // begin在A部落,end没有部落 —— A部落扩张一个村庄
  // end在A部落,begin没有部落 ——A部落扩张一个村庄
  // begin在A部落,end在B部落 ——将AB两个部落合并
  // begin和end在同一个部落,——不可以连接
  if (beginIn != null && endIn != null && beginIn == endIn) {
    return false;
  }
  return true;
}

function link(resultList, tempBegin, tempEnd) {
  var beginIn = null;
  var endIn = null;
  for (var i = 0; i < resultList.length; i++) {
    if (resultList[i].indexOf(tempBegin) > -1) {
      beginIn = resultList[i];
    }
    if (resultList[i].indexOf(tempEnd) > -1) {
      endIn = resultList[i];
    }
  }
  if (beginIn == null && endIn == null) {// 两个点都是新的点(都不在任何部落里)——可以连接,产生新的部落
    var newArr = [];
    newArr.push(tempBegin);
    newArr.push(tempEnd);
    resultList.push(newArr);
  } else if (beginIn != null && endIn == null) {// begin在A部落,end没有部落 —— A部落扩张一个村庄
    beginIn.push(tempEnd);
  } else if (beginIn == null && endIn != null) {// end在A部落,begin没有部落 ——A部落扩张一个村庄
    endIn.push(tempBegin);
  } else if (beginIn != null && endIn != null && beginIn != endIn) {// begin在A部落,end在B部落 ——将AB两个部落合并
    var allIn = beginIn.concat(endIn);
    var needRemove = resultList.indexOf(endIn);
    resultList.splice(needRemove, 1);
    needRemove = resultList.indexOf(beginIn);
    resultList.splice(needRemove, 1);
    resultList.push(allIn);
  }
  tempBegin.neighbor.push(tempEnd);
  tempEnd.neighbor.push(tempBegin);
}

function kruskal(pointSet, distance) {

  var resultList = [];//这里是二维数组,此数组代表的是有多少个"部落"

  while (true) {
    var minDis = max;
    var begin = null;
    var end = null;
    for (var i = 0; i < distance.length; i++) {
      for (var j = 0; j < distance[i].length; j++) {
        var tempBegin = pointSet[i];
        var tempEnd = pointSet[j];
        if (i != j//去掉自己到自己的距离,因为都为0
            && distance[i][j] < minDis
            && canLink(resultList, tempBegin, tempEnd)
           ) {
          minDis = distance[i][j];
          begin = tempBegin;
          end = tempEnd;
        }
      }
    }
    link(resultList, begin, end);
    if (resultList.length == 1 && resultList[0].length == pointSet.length) {//只存在一个部落
      break;
    }
  }

}

kruskal(pointSet, distance);
console.log(pointSet);

二叉搜索树

问题:有一万个数,写一个方法,进行查找,查找给定的数,返回是否存在。尽可能性能好

var arr = [];
for (var i = 0; i < 10000; i++) {
  arr[i] = Math.floor(Math.random() * 10000);
}
var num = 0;
function search(arr, target) {
  for (var i = 0; i < arr.length; i++) {
    num += 1;
    if (arr[i] == target) return true;
  }
  return false;
}
console.log(search(arr, 1000));
console.log(num);

性能差:1.数据结构;2.算法
问题出在数据结构上
二叉搜索树(二叉排序树)

  1. 二叉树
  2. 有排序的效果,左子树节点都比当前节点小,右子树节点都比当前节点大

二叉搜索树

var arr = [];

for (var i = 0; i < 10000; i++) {
  arr[i] = Math.floor(Math.random() * 10000);
}

function Node(value) {
  this.value = value;
  this.left = null;
  this.right = null;
}

var num = 0;
function search(arr, target) {
  for (var i = 0; i < arr.length; i++) {
    num += 1;
    if (arr[i] == target) return true;
  }
  return false;
}

function addNode(root, num) {
  if (root == null) return;
  if (root.value == num) return;//重复的数
  if (root.value < num) {//目标值比当前节点大
    if (root.right == null) root.right = new Node(num);//如果右侧为空,则创建节点
    else addNode(root.right, num);//如果右侧不为空,则向右侧进行递归
  } else {//目标值比当前节点小
    if (root.left == null) root.left = new Node(num);
    else addNode(root.left, num);
  }
}

function buildSearchTree(arr) {
  if (arr == null || arr.length == 0) return null;
  var root = new Node(arr[0]);
  for (var i = 1; i < arr.length; i++) {
    addNode(root, arr[i]);
  }
  return root;
}

var num2 = 0;
function searchByTree(root, target) {//二叉搜索树查找过程 前序遍历
  if (root == null) return false;
  num2 += 1;
  if (root.value == target) return true;
  if (root.value > target) return searchByTree(root.left, target);
  else return searchByTree(root.right, target);
}

console.log(search(arr, 1000));
console.log(num);
 
var root = buildSearchTree(arr);

console.log(searchByTree(root, 1000));
console.log(num2);

平衡二叉树

根节点的左子树与右子树高度差不超过1;
这颗二叉树的每个子树都符合第一条

function Node(value) {
  this.value = value;
  this.left = null;
  this.right = null;
}

var a = new Node("a");
var b = new Node("b");
var c = new Node("c");
var d = new Node("d");
var e = new Node("e");
var f = new Node("f");
var g = new Node("g");
var h = new Node("h");
var j = new Node("j");

a.left = b;
a.right = c;
b.left = d;
// b.right = e;
c.left = f;
c.right = g;
d.right = h;
// e.right = j;

function getDeep(root) {//获取深度
  if (root == null) return 0;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  return Math.max(leftDeep, rightDeep) + 1;//加上当前一层
}

function isBalance(root) {
  if (root == null) return true;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  if (Math.abs(leftDeep - rightDeep) > 1) {//不平衡
    return false;
  } else {
    return isBalance(root.left) && isBalance(root.right);//两边同时平衡  
  }
}

console.log(isBalance(b));

二叉树的单旋

不平衡变成平衡

某一节点不平衡,如果左边浅,右边深,进行左单旋
![1.png](https://img-blog.csdnimg.cn/img_convert/c4b297ecdc21203e39f54c7faeb83d77.png#height=210&id=pFOy7&margin=[object Object]&name=1.png&originHeight=560&originWidth=1168&originalType=binary&ratio=1&size=32846&status=done&style=none&width=437)
![1.png](https://img-blog.csdnimg.cn/img_convert/52e186b2cea7f9980772ee8a7c6a066f.png#height=192&id=RZBWX&margin=[object Object]&name=1.png&originHeight=388&originWidth=396&originalType=binary&ratio=1&size=11316&status=done&style=none&width=196)
旋转节点:不平衡的节点为旋转节点(2)
新根:旋转之后称为根节点的节点(5)
变化分支:父级节点发生变化的那个分支
不变分支:父级节点不变的那个分支

左单旋时:
旋转节点:当前不平衡的节点
新根:右子树的根节点
变化分支:旋转节点的右子树的左子树
不变分支:旋转节点的右子树的右子树

右单旋时:
旋转节点:当前不平衡的节点
新根:左子树的根节点
变化分支:旋转节点的左子树的右子树
不变分支:旋转节点的右子树的左子树
![1.png](https://img-blog.csdnimg.cn/img_convert/52e186b2cea7f9980772ee8a7c6a066f.png#height=192&id=NYz7F&margin=[object Object]&name=1.png&originHeight=388&originWidth=396&originalType=binary&ratio=1&size=11316&status=done&style=none&width=196)
左单旋:

  1. 找到新根5
  2. 找到变化分支
  3. 当前旋转节点的右子树为变化分支
  4. 新根的左孩子为旋转节点
  5. 返回新的根节点
function Node(value) {
  this.value = value;
  this.left = null;
  this.right = null;
}

var node2 = new Node("2");
var node5 = new Node("5");
var node3 = new Node("3");
var node6 = new Node("6");

node2.right = node5;
node5.left = node3;
node5.right = node6;

function getDeep(root) {
  if (root == null) return 0;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  return Math.max(leftDeep, rightDeep) + 1;
}

function isBalance(root) {
  if (root == null) return true;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  if (Math.abs(leftDeep - rightDeep) > 1) {//不平衡
    return false;
  } else {
    return isBalance(root.left) && isBalance(root.right);
  }
}

function leftRotate(root) {
  // 找到新根
  var newRoot = root.right;
  // 找到变化分支
  var changeTree = root.right.left;
  // 当前旋转节点的右孩子为变化分支
  root.right = changeTree;
  // 新根的左孩子为旋转节点
  newRoot.left = root;
  // 返回新的根节点
  return newRoot;
}

function rightRotate(root) {
  // 找到新根
  var newRoot = root.left;
  // 找到变化分支
  var changeTree = root.left.right;
  // 当前旋转节点的左孩子为变化分支
  root.left = changeTree;
  // 新根的右孩子为旋转节点
  newRoot.right = root;
  // 返回新的根节点
  return newRoot;
}

function change(root) {//返回平衡之后的根节点
  if (isBalance(root)) return root;
  // 推荐用后序的方式来判断
  if (root.left != null) root.left = change(root.left);// change后root就变了
  if (root.right != null) root.right = change(root.right);
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  if (Math.abs(leftDeep - rightDeep) < 2) {
    return true;
  } else if (leftDeep > rightDeep) {//不平衡,左边深,需要右旋
    return rightRotate(root);
  } else {//不平衡,右边深,需要左旋
    return leftRotate(root);
  }
}

console.log(isBalance(node2));

var newRoot = change(node2);

console.log(isBalance(newRoot));
console.log(newRoot);

二叉树的双旋

单旋不能满足所有

![image.png](https://img-blog.csdnimg.cn/img_convert/57e095ad41ca0f2ed8b9186b0c1d461f.png#clientId=uae7afcd9-86a1-4&from=paste&height=246&id=u596fa994&margin=[object Object]&name=image.png&originHeight=492&originWidth=550&originalType=binary&ratio=1&size=19729&status=done&style=none&taskId=u931d90fc-5275-437f-8b31-9edaf0f997b&width=275)![image.png](https://img-blog.csdnimg.cn/img_convert/1f8323da5133da1903769690f509b9cc.png#clientId=uae7afcd9-86a1-4&from=paste&height=163&id=u159ee67b&margin=[object Object]&name=image.png&originHeight=325&originWidth=337&originalType=binary&ratio=1&size=17529&status=done&style=none&taskId=uc92bf097-7acb-481d-8d9d-5a5dfdf600d&width=168.5)
![image.png](https://img-blog.csdnimg.cn/img_convert/c017c6f928ec34db0d4c50de590e2c06.png#clientId=uae7afcd9-86a1-4&from=paste&height=167&id=ue3ca2cd6&margin=[object Object]&name=image.png&originHeight=334&originWidth=326&originalType=binary&ratio=1&size=22279&status=done&style=none&taskId=u1c451171-1af7-46bd-bb62-bd55cf350fb&width=163)![image.png](https://img-blog.csdnimg.cn/img_convert/ddca321cd3b2a8380b0a7a2649e374b6.png#clientId=uae7afcd9-86a1-4&from=paste&height=148&id=ue5cb9579&margin=[object Object]&name=image.png&originHeight=434&originWidth=481&originalType=binary&ratio=1&size=20330&status=done&style=none&taskId=u24087d5f-b3e7-4814-af5a-e1eb209408d&width=163.5)
变化分支不可一世唯一的变化分支
如果是 要先进行反向旋转

![image.png](https://img-blog.csdnimg.cn/img_convert/b2d01b7e61adcb522251fcec2b2f9d13.png#clientId=uae7afcd9-86a1-4&from=paste&height=316&id=udc10a394&margin=[object Object]&name=image.png&originHeight=631&originWidth=1231&originalType=binary&ratio=1&size=64566&status=done&style=none&taskId=u6f188120-d8fc-40b2-b426-88e220ea309&width=615.5)
![image.png](https://img-blog.csdnimg.cn/img_convert/3f44a54ad92b65f5d6d30d20eca2d8e0.png#clientId=uae7afcd9-86a1-4&from=paste&height=287&id=uee98a3a4&margin=[object Object]&name=image.png&originHeight=573&originWidth=1216&originalType=binary&ratio=1&size=40370&status=done&style=none&taskId=u11aa05d7-38fb-4b96-83a1-ee77c0b0365&width=608)
二叉树的双旋(左右双旋,右左双旋)
右左双旋:当要对某个节点进行左单旋,如果变化分支是唯一的最深分支,那么要对新根进行右单旋,然后左单旋
反之左右双旋

function Node(value) {
  this.value = value;
  this.left = null;
  this.right = null;
}

var node8 = new Node("8");
var node7 = new Node("7");
var node6 = new Node("6");
var node5 = new Node("5");
var node2 = new Node("2");

node8.left = node7;
node7.left = node6;
node6.left = node5;
node5.left = node2;

function getDeep(root) {
  if (root == null) return 0;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  return Math.max(leftDeep, rightDeep) + 1;
}

function isBalance(root) {
  if (root == null) return true;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  if (Math.abs(leftDeep - rightDeep) > 1) {//不平衡
    return false;
  } else {
    return isBalance(root.left) && isBalance(root.right);
  }
}

function leftRotate(root) {
  // 找到新根
  var newRoot = root.right;
  // 找到变化分支
  var changeTree = root.right.left;
  // 当前旋转节点的右孩子为变化分支
  root.right = changeTree;
  // 新根的左孩子为旋转节点
  newRoot.left = root;
  // 返回新的根节点
  return newRoot;
}

function rightRotate(root) {
  // 找到新根
  var newRoot = root.left;
  // 找到变化分支
  var changeTree = root.left.right;
  // 当前旋转节点的左孩子为变化分支
  root.left = changeTree;
  // 新根的右孩子为旋转节点
  newRoot.right = root;
  // 返回新的根节点
  return newRoot;
}

function change(root) {//返回平衡之后的根节点
  if (isBalance(root)) return root;
  if (root.left != null) root.left = change(root.left);
  if (root.right != null) root.right = change(root.right);
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  if (Math.abs(leftDeep - rightDeep) < 2) {
    return root;
  } else if (leftDeep > rightDeep) {//不平衡,左边深,需要右旋
    var changeTreeDeep = getDeep(root.left.right);
    var noChangeTreeDeep = getDeep(root.left.left);
    if (changeTreeDeep > noChangeTreeDeep) {
      root.left = leftRotate(root.left);
    }
    return rightRotate(root);
  } else {//不平衡,右边深,需要左旋
    var changeTreeDeep = getDeep(root.right.left);
    var noChangeTreeDeep = getDeep(root.right.right);
    if (changeTreeDeep > noChangeTreeDeep) {
      root.right = rightRotate(root.right);
    }
    return leftRotate(root);
  }
  return root;
}

function addNode(root, num) {
  if (root == null) return;
  if (root.value == num) return;
  if (root.value < num) {//目标值比当前节点大
    if (root.right == null) root.right = new Node(num);//如果右侧为空,则创建节点
    else addNode(root.right, num);//如果右侧不为空,则向右侧进行递归
  } else {//目标值比当前节点小
    if (root.left == null) root.left = new Node(num);
    else addNode(root.left, num);
  }
}

function buildSearchTree(arr) {
  if (arr == null || arr.length == 0) return null;
  var root = new Node(arr[0]);
  for (var i = 1; i < arr.length; i++) {
    addNode(root, arr[i]);
  }
  return root;
}

var num2 = 0;
function searchByTree(root, target) {
  if (root == null) return false;
  num2 += 1;
  if (root.value == target) return true;
  if (root.value > target) return searchByTree(root.left, target);
  else return searchByTree(root.right, target);
}
var arr = [];
for (var i = 0; i < 10000; i++) {
  arr.push(Math.floor(Math.random() * 10000));
}

var root = buildSearchTree(arr);
// console.log(searchByTree(root, 1000));
// console.log(num2);

var newRoot = change(root);
// num2 = 0;
// console.log(searchByTree(newRoot, 1000));
// console.log(num2);
console.log(isBalance(newRoot));




// console.log(isBalance(node8));
//
// var newRoot = change(node8);
//
// console.log(isBalance(newRoot));
// console.log(newRoot);

左 左 双 旋 与 右 右 双 旋

function Node(value) {
  this.value = value;
  this.left = null;
  this.right = null;
}

var node8 = new Node("8");
var node7 = new Node("7");
var node6 = new Node("6");
var node5 = new Node("5");
var node2 = new Node("2");

node8.left = node7;
node7.left = node6;
node6.left = node5;
node5.left = node2;

function getDeep(root) {
  if (root == null) return 0;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  return Math.max(leftDeep, rightDeep) + 1;
}

function isBalance(root) {
  if (root == null) return true;
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  if (Math.abs(leftDeep - rightDeep) > 1) {//不平衡
    return false;
  } else {
    return isBalance(root.left) && isBalance(root.right);
  }
}

function leftRotate(root) {
  // 找到新根
  var newRoot = root.right;
  // 找到变化分支
  var changeTree = root.right.left;
  // 当前旋转节点的右孩子为变化分支
  root.right = changeTree;
  // 新根的左孩子为旋转节点
  newRoot.left = root;
  // 返回新的根节点
  return newRoot;
}

function rightRotate(root) {
  // 找到新根
  var newRoot = root.left;
  // 找到变化分支
  var changeTree = root.left.right;
  // 当前旋转节点的左孩子为变化分支
  root.left = changeTree;
  // 新根的右孩子为旋转节点
  newRoot.right = root;
  // 返回新的根节点
  return newRoot;
}

function change(root) {//返回平衡之后的根节点
  if (isBalance(root)) return root;
  if (root.left != null) root.left = change(root.left);
  if (root.right != null) root.right = change(root.right);
  var leftDeep = getDeep(root.left);
  var rightDeep = getDeep(root.right);
  if (Math.abs(leftDeep - rightDeep) < 2) {
    return root;
  } else if (leftDeep > rightDeep) {//不平衡,左边深,需要右旋
    var changeTreeDeep = getDeep(root.left.right);
    var noChangeTreeDeep = getDeep(root.left.left);
    if (changeTreeDeep > noChangeTreeDeep) {
      root.left = leftRotate(root.left);
    }
    var newRoot = rightRotate(root);
    newRoot.right = change(newRoot.right);
    newRoot = change(newRoot);
    return newRoot;
  } else {//不平衡,右边深,需要左旋
    var changeTreeDeep = getDeep(root.right.left);
    var noChangeTreeDeep = getDeep(root.right.right);
    if (changeTreeDeep > noChangeTreeDeep) {
      root.right = rightRotate(root.right);
    }
    var newRoot = leftRotate(root);
    newRoot.left = change(newRoot.left);
    newRoot = change(newRoot);
    return newRoot;
  }
  return root;
}

function addNode(root, num) {
  if (root == null) return;
  if (root.value == num) return;
  if (root.value < num) {//目标值比当前节点大
    if (root.right == null) root.right = new Node(num);//如果右侧为空,则创建节点
    else addNode(root.right, num);//如果右侧不为空,则向右侧进行递归
  } else {//目标值比当前节点小
    if (root.left == null) root.left = new Node(num);
    else addNode(root.left, num);
  }
}

function buildSearchTree(arr) {
  if (arr == null || arr.length == 0) return null;
  var root = new Node(arr[0]);
  for (var i = 1 ; i < arr.length ; i ++) {
    addNode(root, arr[i]);
  }
  return root;
}

var num2 = 0;
function searchByTree(root, target) {
  if (root == null) return false;
  num2 += 1;
  if (root.value == target) return true;
  if (root.value > target) return searchByTree(root.left, target);
  else return searchByTree(root.right, target);
}
var arr = [];
for (var i = 0 ; i < 10000 ; i ++) {
  arr.push(Math.floor(Math.random() * 10000));
}

var root = buildSearchTree(arr);
console.log(searchByTree(root, 1000));
console.log(num2);

var newRoot = change(root);
num2 = 0;
console.log(searchByTree(newRoot, 1000));
console.log(num2);
console.log(isBalance(newRoot));







// console.log(isBalance(node8));
//
// var newRoot = change(node8);
//
// console.log(isBalance(newRoot));
// console.log(newRoot);

树的深度优先搜索

function Node(value) {
  this.value = value;
  this.childs = [];
}

var a = new Node("a");
var b = new Node("b");
var c = new Node("c");
var d = new Node("d");
var e = new Node("e");
var f = new Node("f");

a.childs.push(c);
a.childs.push(f);
a.childs.push(b);
b.childs.push(d);
b.childs.push(e);

function deepSearch(root, target) {
  if (root == null) return false;
  if (root.value == target) return true;
  var result = false;
  for (var i = 0 ; i < root.childs.length ; i ++) {
    result |= deepSearch(root.childs[i], target);
  }
  return result ? true : false;
}

console.log(deepSearch(a, "n"))

树的广度优先搜索

  function Node(value) {
      this.value = value;
      this.childs = [];
  }

  var a = new Node("a");
  var b = new Node("b");
  var c = new Node("c");
  var d = new Node("d");
  var e = new Node("e");
  var f = new Node("f");

  a.childs.push(c);
  a.childs.push(f);
  a.childs.push(b);
  b.childs.push(d);
  b.childs.push(e);


  function bfs(roots, target) {
      if (roots == null || roots.length == 0) return false;
      var childs = [];
      for (var i = 0 ; i < roots.length ; i ++) {
          if (roots[i].value == target) {
              return true;
          } else {
              childs = childs.concat(roots[i].childs);
          }
      }
      return bfs(childs, target);
  }

  console.log(bfs([a], "n"));

图的深度优先

不要形成环

function Node(value) {
  this.value = value;
  this.neighbor = [];
}

var a = new Node("a");
var b = new Node("b");
var c = new Node("c");
var d = new Node("d");
var e = new Node("e");

a.neighbor.push(b);
a.neighbor.push(c);
b.neighbor.push(a);
b.neighbor.push(c);
b.neighbor.push(d);
c.neighbor.push(a);
c.neighbor.push(b);
c.neighbor.push(d);
d.neighbor.push(b);
d.neighbor.push(c);
d.neighbor.push(e);
e.neighbor.push(d);

function deepSearch(node, target, path) {
  if (node == null) return false;
  if (path.indexOf(node) > -1) return false;
  if (node.value == target) return true;
  path.push(node);
  var result = false;
  for (var i = 0 ; i < node.neighbor.length ; i ++) {
    result |= deepSearch(node.neighbor[i], target, path);//一真为真
  }
  return result ? true : false;
}

console.log(deepSearch(b, "d", []));

图的广度优先

function Node(value) {
    this.value = value;
    this.neighbor = [];
}

var a = new Node("a");
var b = new Node("b");
var c = new Node("c");
var d = new Node("d");
var e = new Node("e");

a.neighbor.push(b);
a.neighbor.push(c);
b.neighbor.push(a);
b.neighbor.push(c);
b.neighbor.push(d);
c.neighbor.push(a);
c.neighbor.push(b);
c.neighbor.push(d);
d.neighbor.push(b);
d.neighbor.push(c);
d.neighbor.push(e);
e.neighbor.push(d);

function bfs(nodes, target, path) {
    if (nodes == null || nodes.length == 0) return false;
    var nextNodes = [];
    for (var i = 0 ; i < nodes.length ; i ++) {
        if (path.indexOf(nodes[i]) > -1) continue;
        path.push(nodes[i]);
        if (nodes[i].value == target) return true;
        else nextNodes = nextNodes.concat(nodes[i].neighbor);
    }
    return bfs(nextNodes, target, path);
}

console.log(bfs([c], "n", [])); 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值