查找算法

159 阅读1分钟

顺序查找

又叫做顺序查找,查找过程:从表中第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查的记录;如果直到最后一个(或第一个)记录,其关键字和给定值比较都不相等,则表中没有所查的记录,查找不成功。

查找算法实现:

// a为数组,n为要查找的数组长度,key为要查找的关键字
function sequentialSearch(a, n, key) {
    var i;
    for (i=1; i<n; i++) {
        if (a[i] === key) {
            return i;
        }
    }
    return 0;
}

该实现每次勋魂时都需要对i是否越界,即是否小于等于n作判断。

优化实现(设置哨兵):

function sequentialSearch2(a, n, key) {
    var i = 0;
    a[n] = key;
    while (a[i] !== a[n]) {
        i++;
    }
    return i < n ? i+1 : 0;
}

折半查找

折半查找(Binary Search)技术,又称为二分查找。前提线性表中的记录必须关键码有序,线性表必须采用顺序存储。在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区域继续查找。不断重复上述过程,直到查找成功,或所有查找区域无记录,查找失败为止。

function binarySearch(a, n, key) {
    var low, high, mid;
    low = 0;
    high = n - 1;
    while (low <= high) {
        mid = Math.floor((low + high) / 2);
        if (key < a[mid]) {
            high = mid - 1;
        } else if (key > a[mid]) {
            low = mid + 1;
        } else {
            return mid + 1;
        }
    }
    return 0;
}

插值查找

插值查找(Interpolation Search)是根据要查找的关键字key与查找表中最大最小记录的关键字比较后查找方法,其核心就是插值的计算公式:(key-a[low]) / (a[high]-a[low])

function InsertionSearch(arr, val, start, end) {
  var end = end || arr.length - 1;
  var start = start || 0;
  var mid = start + (val - arr[low]) / (arr[end] - arr[start]) * (end - start);
  if (arr[mid] == val) {
    return mid;
  }
  if (arr[mid] > val) {
    return InsertionSearch(arr, val, start, mid - 1);
  }
  else {
    return InsertionSearch(arr, val, mid + 1, end);
  }
}

斐波那契查找

function search(array, value) {
  let low = 0, high = array.length - 1, n = array.length - 1;
  let mid, k = 0;
  //构建一个长度大于array数组的斐波那契数组
  var F = [];
  F[0] = 0;
  F[1] = 1;
  for (var i = 2; i < high + 5; i++) {
    F[i] = F[i - 1] + F[i - 2];
  }
  while (high > F[k] - 1) { //寻找第k项
    k++;
  }
  for (let i = high; i < F[k] - 1; i++) { //补全有序数组
    array[i] = array[high];
  }
  while (low <= high) {
    mid = low + F[k - 1] - 1;
    if (array[mid] > value) {
      high = mid - 1;
      k = k - 1; //长度缩减为F[k-1]-1
    } else if (array[mid] < value) {
      low = mid + 1;
      k = k - 2; //长度缩减为F[k-2]-1
    } else {
      if (m <= n) //相等则找到位置
        return mid;
      else {
        return n; //大于原始长度,则说明等于数组最后一项 
      }
    }
    return -1;
  }
}

二叉排序树查找操作

二叉排序树(Binary Sort Tree),又称为二叉查找树。它或者是一颗空数=树,或者是具有下列性质的二叉树。

  • 若它的左子树不为空,则左子树上所有的节点值均小于它的根结构的值;

  • 若它的右子树不为空,则右子树上所有的节点值均大于它的根节点的值;

    function TreeNode(val, left, right) { this.val = (val === undefined ? 0 : val); this.left = (left === undefined ? null : left); this.right = (right === undefined ? null : right); }

    function searchBST(T, key) { if (!T) { return false; } else if (key === T.val) { return true; } else if (key < T.val) { return seatchBST(T.left, key); } else { return searchBST(T.right, key); } }

平衡二叉树:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1 。

function TreeNode(val, left, right) {
    this.val = (val === undefined ? 0 : val);
    this.left = (left === undefined ? null : left);
    this.right = (right === undefined ? null : right);
}
var isBalanced = function(root) {    if (!root) {return true}    if (Math.abs(depth(root.left) - depth(root.right)) > 1) {        return false;    }    return isBalanced(root.left) && isBalanced(root.right);    function depth(node) {        if (!node) {return 0}        const left = depth(node.left);        const right = depth(node.right);        return Math.max(left, right) + 1;    }};

对称二叉树:给定一个二叉树,检查它是否是镜像对称的。

var isSymmetric = function(root) {
    if (!root) {return true;}
    function leftAndRight(left, right) {
        if (!left && !right) {
            return true;
        }
        if (!left || !right) {
            return false;
        }
        if (left.val !== right.val) {
            return false;
        }
        return leftAndRight(left.left, right.right) && leftAndRight(left.right, right.left);
    }
    return leftAndRight(root.left, root.right);
};