成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Javacript二叉樹常見算法實現(xiàn)及快速排序求第K大值

leeon / 1609人閱讀

摘要:后面也寫了幾種常見的排序算法,并用快排求第大值,另外如果之前版的作者看到的話可以留言,我會標(biāo)明文章引用。

之前實習(xí)筆試的時候刷題一直用的java,也參考某篇文章寫過java版的二叉樹常見算法,因為馬上要轉(zhuǎn)正面試了,這幾天都在準(zhǔn)備面試,就把之前的翻出來用javascript重新寫了一遍,二叉樹基本都是遞歸處理的,也比較簡單,就當(dāng)做熱身。后面也寫了幾種常見的排序算法,并用快排求第K大值,另外如果之前java版的作者看到的話可以留言,我會標(biāo)明文章引用。

Javacript二叉樹常見算法實現(xiàn) 節(jié)點構(gòu)造函數(shù)和二叉樹構(gòu)造函數(shù)
function Node(key) {
    this.key = key;
    this.left = null;
    this.right = null;
}
function binaryTree() {
    this.root = null;
}
插入節(jié)點生成二叉樹
binaryTree.prototype.insert = function(root, key) {
    var node = new Node(key);
    if (root === null) { //樹根節(jié)點為空則將此節(jié)點作為根節(jié)點
        this.root = node;
    } else if (node.key < root.key) { //小于左孩子節(jié)點則要么作為左子節(jié)點要么遞歸插入左部門
        if (root.left === null) {
            root.left = node;
        } else {
            this.insert(root.left, key);
        }
    } else { //大于右孩子節(jié)點則要么作為右子節(jié)點要么遞歸插入到右部分
        if (root.right === null) {
            root.right = node;
        } else {
            this.insert(root.right, key);
        }
    }
}
先序遍歷
//先序遍歷遞歸方法
binaryTree.prototype.preOrder = function(node) {
    if (node !== null) {
        console.log(node.key); //先打印當(dāng)前結(jié)點
        this.inOrder(node.left); //打印左結(jié)點
        this.inOrder(node.right); //打印右結(jié)點
    }
}

//先序遍歷非遞歸方法
//首先將根節(jié)點入棧,如果棧不為空,取出節(jié)點打印key值,然后依次取右節(jié)點和左節(jié)點入棧,依次重復(fù)
binaryTree.prototype.preOrder2 = function(node) {
    let stack = [];
    stack.push(node);
    while (stack.length > 0) {
        let n = stack.pop();
        console.log(n.key);
        if (n.right != null) {
            stack.push(n.right);
        }
        if (n.left != null) {
            stack.push(n.left);
        }
    }
}
中序遍歷
//中序遍歷遞歸方法
binaryTree.prototype.inOrder = function(node) {
    if (node !== null) {
        this.inOrder(node.left);
        console.log(node.key);
        this.inOrder(node.right);
    }
}

//中序遍歷非遞歸方法
//依次取左節(jié)點入棧直到左下角節(jié)點入棧完畢,彈出節(jié)點打印key,如果該節(jié)點有右子節(jié)點,將其入棧
binaryTree.prototype.inOrder2 = function(node) {
    let stack = [];
    while (node != null || stack.length) {
        if (node != null) {
            stack.push(node);
            node = node.left;
        } else {
            let n = stack.pop();
            console.log(n.key);
            node = n.right;
        }
    }
}
后序遍歷
binaryTree.prototype.postOrder = function(node) {
    if (node !== null) {
        this.inOrder(node.left);
        this.inOrder(node.right);
        console.log(node.key);
    }
}
求樹的深度
binaryTree.prototype.treeDepth = function(node) {
    if (node === null) {
        return 0;
    }
    let left = this.treeDepth(node.left);
    let right = this.treeDepth(node.right);
    return (left > right) ? (left + 1) : (right + 1);
}
判斷兩棵樹結(jié)構(gòu)是否相同
binaryTree.prototype.structCmp = function(root1, root2) {
    if (root1 == null && root2 == null) { //根節(jié)點都為空返回true
        return true;
    }
    if (root1 == null || root2 == null) { //根節(jié)點一個為空一個不為空返回false
        return false;
    }
    let a = this.structCmp(root1.left, root2.left); //都有孩子節(jié)點則遞歸判斷左邊是不是相同并且右邊也相同
    let b = this.structCmp(root1.right, root2.right);
    return a && b; //左子樹相同并且右子樹相同
}
得到第k層節(jié)點個數(shù)
binaryTree.prototype.getLevelNum = function(root, k) {
    if (root == null || k < 1) {
        return 0;
    }
    if (k == 1) {
        return 1;
    }
    return this.getLevelNum(root.left, k - 1) + this.getLevelNum(root.right, k - 1); //從左子樹角度看,根節(jié)點第k層就是相對于左子樹k-1層,把左子樹右子樹k-1層相加即可
}
求二叉樹的鏡像
binaryTree.prototype.mirror = function(node) {
    if (node == null) return;
    [node.left, node.right] = [node.right, node.left]; //交換左右子樹并依次遞歸
    this.mirror(node.left);
    this.mirror(node.right);
}
最近公共祖先節(jié)點
binaryTree.prototype.findLCA = function(node, target1, target2) {
    if (node == null) {
        return null;
    }
    if (node.key == target1 || node.key == target2) { //如果當(dāng)前結(jié)點和其中一個節(jié)點相等則當(dāng)前結(jié)點為公共祖先
        return node;
    }
    let left = this.findLCA(node.left, target1, target2);
    let right = this.findLCA(node.right, target1, target2);
    if (left != null && right != null) { //如果左右子樹都沒找到則目標(biāo)節(jié)點分別在左右子樹,根節(jié)點為其祖先
        return node;
    }
    return (left != null) ? left : right; // 找到的話返回
}
測試用

var tree = new binaryTree();
let arr = [45, 5, 13, 3, 23, 7, 111];
arr.forEach((node) => {

tree.insert(tree.root, node);

});

var tree2 = new binaryTree();
let arr2 = [46, 6, 14, 4, 24, 8, 112];
arr2.forEach((node) => {

tree2.insert(tree2.root, node);

});

tree.preOrder(tree.root);
tree.preOrder2(tree.root);
tree2.inOrder(tree2.root);
tree.inOrder2(tree.root);
let depth = tree.treeDepth(tree.root);
console.log(depth);
let isstructCmp = tree2.structCmp(tree.root, tree2.root);
console.log(isstructCmp);
let num = tree.getLevelNum(tree.root, 4);
console.log(num);
tree.mirror(tree.root);
tree.inOrder(tree.root);
let n = tree.findLCA(tree.root, 111, 3);
console.log(n);

快速排序求第K大值 快速排序
function quickSort(array) {
  if(array.length <= 1){
      return array;
  }
  let middle = Math.floor(array.length / 2)
  let pivot = array.splice(middle, 1);
  let left =[], right = [];
  for(let i = 0; i < array.length; i++) {
      if(array[i] < pivot) {
          left.push(array[i]);
      } else {
          right.push(array[i]);
      }
      
  }
  return quickSort(left).concat(pivot, quickSort(right));
}
快速排序改進求第K大值

思想是通過快排把數(shù)組切割成左中右三部分,將K與右邊數(shù)組(當(dāng)然選左邊數(shù)組也可以)長度作比較,如果右邊數(shù)組長度為K-1,則中間元素即為第K大值,如果右邊數(shù)組長度大于等于K,則第K大元素肯定在右邊,則只需要對右邊數(shù)組遞歸求K大值,如果右邊數(shù)組長度小于K-1,則第K大值在左邊,在左數(shù)組求第k-1-right.length大值即可

function getK(array, k) {
  if(array.length <= 1){
      return array;
  }
  let middle = Math.floor(array.length / 2)
  let pivot = array.splice(middle, 1);
  let left =[], right = [];
  for(let i = 0; i < array.length; i++) {
      if(array[i] < pivot) {
          left.push(array[i]);
      } else {
          right.push(array[i]);
      }
      
  }
  if(right.length == k - 1){
      return pivot;
  } else if (right.length >= k) {
      return getK(right, k);
  } else {
      return getK(left, k-right.length-1);
  }
}

另外此方法也不是最佳解法,還有一種比較好的解法是利用建立K個元素的最小堆,新元素替換堆頂元素并調(diào)整堆,最后得到的K個元素即為最大的K個元素,時間復(fù)雜度NlogK

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/108343.html

相關(guān)文章

  • 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)和算法概念

    摘要:數(shù)據(jù)結(jié)構(gòu)程序數(shù)據(jù)結(jié)構(gòu)算法數(shù)據(jù)結(jié)構(gòu)基本概念數(shù)據(jù)的邏輯結(jié)構(gòu)反映數(shù)據(jù)元素之間的關(guān)系的數(shù)據(jù)元素集合的表示。這兩部分信息組成數(shù)據(jù)元素的存儲映象,稱為結(jié)點。 本文涉及更多的是概念,代碼部分請參考之前寫過的 2 篇博客 基于 Javascript 的排序算法 基于 javascript 的基本數(shù)據(jù)結(jié)構(gòu)和查找算法 本文主要是基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)和算法概念,可能部分地方會涉及更高級的算法和算法,具體內(nèi)容以...

    fsmStudy 評論0 收藏0
  • PHP面試:說下什么是堆和堆排序

    摘要:一個常見的例子就是優(yōu)先隊列,還有排序算法之一的堆排序。另外我們還將學(xué)習(xí)堆排序,并將使用實現(xiàn)堆。堆排序在堆排序中,我們需要用給定的值構(gòu)建一個一個堆。偽代碼如下從上面的偽代碼可以看到,堆排序的第一步就是構(gòu)建一個堆。 堆是什么? 堆是基于樹抽象數(shù)據(jù)類型的一種特殊的數(shù)據(jù)結(jié)構(gòu),用于許多算法和數(shù)據(jù)結(jié)構(gòu)中。一個常見的例子就是優(yōu)先隊列,還有排序算法之一的堆排序。這篇文章我們將討論堆的屬性、不同類型的堆...

    twohappy 評論0 收藏0
  • 面試算法實踐與國外大廠習(xí)題指南

    摘要:面試算法實踐與國外大廠習(xí)題指南翻譯自維護的倉庫,包含了在線練習(xí)算法概述與大廠習(xí)題實戰(zhàn)等內(nèi)容。面試算法實踐與國外大廠習(xí)題指南在線練習(xí)在線面試編程數(shù)據(jù)結(jié)構(gòu)鏈表即是由節(jié)點組成的線性集合,每個節(jié)點可以利用指針指向其他節(jié)點。 面試算法實踐與國外大廠習(xí)題指南 翻譯自 Kevin Naughton Jr. 維護的倉庫 interviews,包含了在線練習(xí)、算法概述與大廠習(xí)題實戰(zhàn)等內(nèi)容。筆者發(fā)現(xiàn)正好和...

    genedna 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<