Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVL树 #233

Open
louzhedong opened this issue Oct 22, 2020 · 0 comments
Open

AVL树 #233

louzhedong opened this issue Oct 22, 2020 · 0 comments

Comments

@louzhedong
Copy link
Owner

AVL树

AVL树是一种平衡二叉搜索树

它具有以下性质:

它是一颗空树或者它的左右子树的高度差的绝对值不超过1,并且左右两颗子树都是平衡二叉树

windows对进程地址空间的管理用到了AVL树

实现

/**
 * AVL树(平衡二叉树)
 * 是一颗空树
 * 或者它的左右子树的高度差的绝对值不超过1,并且左右两颗子树都是平衡二叉树
 * 平衡因子,左子树和右子树的高度差
 */

function Node(val) {
  this.val = val;
  this.left = null;
  this.right = null;
  this.height = 1;
}

function getHeight(node) {
  if (node) {
    return node.height;
  } else {
    return 1;
  }
}

// LL 右旋转
function rightRotate(node) {
  const x = node.left;
  const temp = x.right;
  node.left = temp;
  x.right = node;
  node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
  x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;

  return x;
}

// RR 左旋转
function leftRotate(node) {
  const x = node.right;
  const temp = x.left;
  node.right = temp;
  x.left = node;
  node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
  x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;

  return x;
}

// LR 先左旋到LL,再右旋
function leftRightRotate(node) {
  const x = node.left;
  node.left = leftRotate(x);
  return rightRotate(node);
}


// RL 先右旋到RR, 再左旋
function rightLeftRotate(node) {
  const x = node.right;
  node.right = rightRotate(x);
  return leftRotate(node);
}

// 插入操作,往根节点为node的树中插入元素element
function insert(node, element) {
  // 如果节点不存在,则创建一个节点
  if (node === null) {
    node = new Node(element);
  }
  else if (element < node.val) {  // 插入左子树
    node.left = insert(node.left, element);
    if (getHeight(node.left) - getHeight(node.right) === 2) {
      if (element < node.left.val) { // LL 
        node = rightRotate(node);
      } else {  // LR
        node = leftRightRotate(node);
      }
    }
  }
  else if (element > node.val) {  // 插入右子树
    node.right = insert(node.right, element);
    if (getHeight(node.right) - getHeight(node.left) === 2) {
      if (element > node.right.val) {  // RR
        node = leftRotate(node);
      } else {  // LR
        node = rightLeftRotate(node);
      }
    }
  }
  node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
  return node;
}

function minimum(node) {  // 寻找树的最小节点
  let temp = node;
  while (node.left) {
    temp = node.left;
  }
  return temp;
}

function getBalanceFactor(node) {
  if (node === null) {
    return 0;
  }
  return getHeight(node.left) - getHeight(node.right);
}

// 删除节点
function remove(node, element) {
  if (node === null) {
    return null;
  }
  let retNode = null;
  if (element < node.val) {  // 如果比当前节点小
    node.left = remove(node.left, element);
    retNode = node;
  } else if (element > node.val) {  // 如果比当前节点大
    node.right = remove(node.right, element);
    retNode = node;
  } else {  // 如果跟当前元素一样大
    if (node.left === null) {  // 左子树为空
      const rightNode = node.right;
      node.right = null;
      retNode = rightNode;
    } else if (node.right === null) {  // 右子树为空
      const leftNode = node.left;
      node.left = null;
      retNode = leftNode;
    } else { // 左右均不为空
      let replacer = minimum(node.right);
      replacer.right = remove(node.right, replacer.val);
      replacer.left = node.left;

      node.left = node.right = null;
      retNode = replacer;
    }
  }

  if (retNode === null) {
    return null;
  }

  retNode.height = Math.max(getHeight(retNode.left), getHeight(retNode.right)) + 1;
  const balanceFactor = getBalanceFactor(retNode);

  if (balanceFactor > 1 && getBalanceFactor(retNode.left) >= 0) {  // LL
    return rightRotate(retNode);
  }
  if (balanceFactor < -1 && getBalanceFactor(retNode.right) <= 0) {  // RR
    return leftRotate(retNode);
  }
  if (balanceFactor > 1 && getBalanceFactor(retNode.left) < 0) {  // LR
    return leftRightRotate(retNode);
  }
  if (balanceFactor < -1 && getBalanceFactor(retNode.right) > 0) {
    return rightLeftRotate(retNode)
  }
  return retNode;
}


let root = new Node(10);
root = insert(root, 8);
root = insert(root, 6);
console.log(root);

root = remove(root, 8);
console.log(root);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant