主頁 > 前端設計 > 前端必看js資料結構與演算法(佇列,鏈表,集合,字典,樹,圖,堆)

前端必看js資料結構與演算法(佇列,鏈表,集合,字典,樹,圖,堆)

2021-10-13 08:29:11 前端設計

佇列

佇列簡介

  • 一個先進先出的資料結構
  • js中沒有佇列,但是可以用Array實作對佇列的所有功能

image.png
使用陣列模擬先進先出的場景

const queue = [] 
// 進佇列
queue.push(1)
queue.push(2)

// 出佇列
const itme1 = queue.shift()
const itme2 = queue.shift()


什么時候用

  1. 食堂排隊打飯
  2. 所有先進先出的場景
  3. js 異步中的任務佇列
    一個leetcode題 第933題

鏈表

鏈表是什么

  • 多個元素組成的串列
  • 勻速存盤不連續, 用next指標連在一起

image.png

陣列 vs 鏈表

  • 陣列:增刪非收尾元素是往往需要移動元素
  • 鏈表:增刪非收尾元素,不需要移動元素,只需要更改next指標即可

js中的鏈表

  • js沒有鏈表的資料結構
  • 可以用Object模擬鏈表

const a = { val: 'a' }
const b = { val: 'b' }
const c = { val: 'c' }
const d = { val: 'd' }
a.next = b
b.next = c
c.next = d

// 遍歷
let point = a
while (point) {
    console.log(point.val)
    point = point.next
}

// 插入
(c-d)中插入d

const e = {val:'e'}
c.next = e
e.next = d


// 洗掉 (洗掉e)
c.next = d

leetcode練習:第83題-洗掉鏈表重復元素

var deleteDuplicates = function(head) {
  // 定義鏈表的一個頭部的指標
  let p = head
  while(p && p.next) {
      if(p.val === p.next.val) {
        // 洗掉鏈表的一項
          p.next = p.next.next
      }else {
      // 不相同的時候再移動指標
           p = p.next
      }
  }
  return head
 
};

  • 前端原型鏈的鏈表 JavaScript 一文搞定理解原型與原型鏈
    手寫一個instanceof
function myInstanceof (A, B) {
  // 遍歷鏈表
  let p =  A
  while (p) {
    p = p.__proto__
    // B的 prototype 屬性是否出現在A實體物件的原型鏈上
    if (p === B.prototype) {
      return true
    }
   
  }
  return false
}
function Foo () {}
var f = new Foo()
console.log(myInstanceof(f, Foo)); // true
console.log(myInstanceof(f, Object)); // true

集合

集合簡介

  • 一種無序且唯一的資料結構
  • ES6中有集合, 名為Set
  • 集合常用操作: 去重,判斷某元素是否在集合中,求交集
// 去重
const arr = [1,1,2,3,4,3]
const arr2 = [...new Set(arr)]

// 判斷元素是否在集合中
let set = new Set(arr)

// add 方法
set.add(1)
set.add('text')
set.add({a:1,b:2})

// has方法
const has =set.has(3)

// delete方法
set.delete(1)

// 獲取size 方法
console.log(set.size)
// 求交集
const set2 = new Set([2,3])
const set3 new Set([...set]).filter(item => set2.has(item))

// 求差集
const set2 = new Set([2,3])
const set4 = new Set([...set]).filter(item => !set2.has(item))

// 陣列轉為set
set2 = new Set([1,2,3])

// 迭代方法 fot ..of
for (let item of set) console.log(item)
for (let item of set.keys())) console.log(item)
for (let item of set.values()) console.log(item)
for (let item of set.entrise()) console.log(item)

補充說明迭代
內置迭代器:

可迭代的物件,都內置以下3種迭代器

entries(): 回傳一個迭代器,值為鍵值對

values(): 回傳一個迭代器, 值為集合的值

keys(): 回傳一個迭代器,值為集合中的所有鍵

let userList = [ 'ghostwu', '悟空', '八戒' ];

for ( let name of userList.entries() ) {
    console.log( name );
}

let set = new Set( [ 10, 20, 30 ] );
for ( let num of set.entries() ){
    console.log( num );
}

let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] );
for ( let detail of map.entries() ){
    console.log( detail );
}

y2lP#f9L1r0ZWXu#82u90g==.png

字典

字典簡介

  • 與集合相似, 字典也是一種存盤為一值的資料結構, 但他是以鍵值對的形式存盤
  • ES6中有字典–>Map(映射)
  • 常見操作 增(set) 刪(delete) 改(set) 查(get)
const m = new Map()

//增
m.set('a','aaa')

// 刪
m.delete('a')
m.clear()

// 改
m.set('a','aaaaa')

// 查
m.get('a')

使用Map取兩個陣列的交集

var intersection = function(nums1, nums2) {
  // new Set(nums1) 去重
  return  [...new Set(nums1)].filter(item => nums2.includes(item))
};

樹簡介

  • 一種分層資料的抽象模型
  • 前端作業中常見的樹包括:DOM樹,級聯選擇,樹形控制元件…
  • js中沒有樹,但是可以用Array 和Object構建樹
  • 樹的常用操作: 深度/廣度優先遍歷 , 先中后序遍歷

樹的深度/廣度優先遍歷

  • 深度優先遍歷: 盡可能深的搜索樹的分支:遞回
    1. 訪問根節點
    2. 對根節點的children挨個進行深度優先遍歷
      impicture_20210925_155733.png
const tree = {
  val: 'a',
  children: [
    {
      val: 'b',
      children: [
        {
          val: 'd',
          children: [
            
          ]
        },
        {
          val: 'e',
          children: [
            
          ]
        }
      ]
    },
    {
      val: 'c',
      children: [
        {
          val: 'f',
          children: [
            
          ]
        },
        {
          val: 'g',
          children: [
            
          ]
        }
      ]
    }
  ]
}
const dfs =(root) => {
  console.log(root.val)
  root.children.forEach(dfs)
}

dfs(tree)

列印結果

impicture_20210925_161217.png

  • 廣度優先遍歷:先訪問離根節點最近的節點
    1. 新建一個佇列, 把根節點入隊
    2. 把對頭出隊并訪問
    3. 把對頭的children挨個入隊
    4. 重復第二,第三,直到佇列為空

impicture_20210925_155839.png



const bfc = (root) => {
  const q = [root]
  while (q.length > 0) {
    const n = q.shift()
    console.log(n.val)
    n.children.forEach(child => {
      q.push(child)
    })
  }
}

列印結果:

impicture_20210925_162636.png

二叉樹的先中后序遍歷

二叉樹是什么?

impicture_20210925_162952.png

  • 樹中每個節點最多只能有兩個子節點

  • 在js中通常用Object來模擬二叉樹

const binaryTree = {
  val: 1,
  left: {
    val:2,
    left: null,
    right: null
  },
  right: {
    val:3,
    left: null,
    right: null
  }
}

先序遍歷演算法

  1. 訪問節點
  2. 對根節點的子樹進行先序遍歷
  3. 對根節點的子樹進行先序遍歷

遍歷順序如圖
impicture_20210925_171603.png

定義一棵樹


const binaryTree = {
 val: 1,
 left: {
   val: 2,
   left: {
     val: 4,
     left: null,
     right: null,
   },
   right: {
     val: 5,
     left: {
       val: 7,
       left: null,
       right: null,
     },
     right: null,
   },
 },
 right: {
   val: 3,
   left: null,
   right: {
     val: 6,
     left: null,
     right: null,
   },
 },
};

遞回版:

const preorder = root => {
  if (!root) return;
  console.log(root.val);
  preorder(root.left);
  preorder(root.right);
};
preorder(binaryTree);

非遞回(堆疊特性):

const preorder = root => {
  if (!root) return;
  const stack = [root];
  while (stack.length) {
    const n = stack.pop();
    console.log(n.val);
    n.right && stack.push(n.right);
    n.left && stack.push(n.left);
  }
};
preorder(binaryTree);

列印結果:

impicture_20210925_192938.png

中序遍歷演算法

  1. 對根節點的子樹進行中序遍歷
  2. 訪問接節點
  3. 對根節點的子樹進行中序遍歷

遍歷順序如圖
impicture_20210925_191542.png

還是使用binaryTree這個樹
遞回版實作:

const inorder = root => {
  if(!root) return 
  inorder(root.left)
  console.log(root.val)
  inorder(root.right)
}
inorder(binaryTree)

非遞回版實作:

const inorder = root => {
  if (!root) return;
  const stack = [];
  let p = root;
  while (stack.length || p) {
    while (p) {
      stack.push(p);
      p = p.left;
    }
    const n = stack.pop();
    console.log(n.val);
    p = n.right;
  }
}
inorder(binaryTree)

列印結果:

impicture_20210925_193158.png

后序遍歷演算法

  1. 對根節點的子樹進行中序遍歷
  2. 對根節點的子樹進行中序遍歷
  3. 訪問接節點

impicture_20210925_193507.png

還是使用binaryTree這個樹
遞回版實作:

const postorder = (root) => {
  if (!root) return;
  postorder(root.left);
  postorder(root.right);
  console.log(root.val);
};
postorder(binaryTree);

非遞回版實作:

const inorder = root => {
  if (!root) return;
  const outputStack = [];
  const stack = [root];
  while (stack.length) {
    const n = stack.pop();
    outputStack.push(n);
    if (n.left) stack.push(n.left);
    if (n.right) stack.push(n.right);
  }
  while (outputStack.length) {
    const n = outputStack.pop();
    console.log(n.val);
  }
}
inorder(binaryTree)

列印結果:

impicture_20210925_193720.png

前端與樹

遍歷JSON的所有節點值

使用深度優先遍歷

const json = {
  a: { b: { c: 1 } },
  d: [1, 2],
};
// 深度優先遍歷
const dfs = (n, path) => {
  console.log(n, path);
  Object.keys(n).forEach((k) => {
    dfs(n[k], path.concat(k));
  });
};
dfs(json, []);

列印結果

8#N46LVi5WYavPpD0kJxEA==.png

圖是什么

  • 圖是網路結構的抽象模型, 是一組由邊連接的節點
  • 圖可以表示任何二元關系, 比如路,航班
  • js沒有圖, 可以用Array Object模擬

eCbZ97wow3zli41Hgl62LA==.png

圖的表示法

鄰接矩陣

Efua5ZlxkTcN1VY$4z3r1g==.png

m3#LjYpWKEuLT8mWVYd#Lg==.png

鄰接表

XVIV5XKQ==.png

yMJh03aIcxtiz2ymXyoyiA==.png

圖的遍歷

  • 深度優先遍歷: 盡可能深的搜索圖的分支
  1. 訪問根節點
  2. 對根節點的沒訪問過得相鄰節點挨個進行深度優先遍歷

7ThsFuwR4YTamHXonaJgZw==.png
定義一個圖

const graph = {
  0:[1,2],
  1:[2],
  2:[0,3],
  3:[3]
}

使用深度優先遍歷


const visited = new Set()
const dfs = n => {
  console.log(n)
  visited.add(n)
  graph[n].forEach(c => {
    if(!visited.has(c)) {
      dfs(c)
    }
  })
}
dfs(2)

列印結果

impicture_20210928_192607.png

  • 廣度優先遍歷: 先訪問離根節點最近的節點
  1. 新建一個佇列, 把根節點入隊
  2. 把隊頭出隊并訪問
  3. 把隊頭的沒訪問過得相鄰節點入隊
  4. 重復第二 三步, 直到佇列為空

impicture_20210928_192719.png

const bfs = node => {
  const visited = new Set()
  visited.add(node)
  const q = [node]
  while (q.length) {
    const n = q.shift()
    console.log(n)
    graph[n].forEach(c => {
      if(!visited.has(c)) {
        q.push(c)
        visited.add(c)
      }
    })
  }
}
bfs(2)

列印結果:

impicture_20210928_195138.png

堆是什么

  • 堆是一種特殊的完全二叉樹
    完全二叉樹如圖:
    5SDCt6K6Cahj5FnPmtHr8w==.png

  • 所有的節點都大于等于(最大堆)或小于等于(最小堆)他的節點

  • js中通常用陣串列述堆

  • 左側子節點的位置是2 * index + 1

  • 右側子節點的位置是2 * index + 2

  • 父節點的位置是(index - 1) / 2

rxkochTNbMbEkci4KeUmLQ==.png

堆的應用

  • 對能高效快速地找出最大值和最小值, 時間復雜度:O(1)
  • 找出第K個最大(小)元素

第K個最大元素

  1. 構建一個最小堆, 并將元素依次插入堆中
  2. 當堆的容量超過K, 就是洗掉堆頂
  3. 插入結束后, 堆頂就是第K個最大元素

js實作最小堆類

  • 構建一個類
  1. 在類里, 宣告一個陣列, 用來裝元素
  2. 主要方法: 插入, 洗掉堆頂, 獲取堆頂, 獲取堆大小
  • 插入
  1. 將值插入堆的底部,即陣列的尾部
  2. 然后上移: 將這個值和它的防父節點進行交換, 直到父節點小于等于這個插入的值
  3. 大小為k的堆中插入元素的時間復雜度為O(logk)
  • 洗掉堆頂
  1. 用陣列尾部元素替換堆頂(直接洗掉堆頂會破壞堆結構)
  2. 然后下移: 將新堆頂和它的子節點進行交換, 直到子節點大于等于這個新堆頂
  3. 大小為k的堆中洗掉堆頂得時間復雜度為O(logk)

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/310594.html

標籤:其他

上一篇:3、Vue 筆記(axios、Vue 影片、Vue 組件、使用 this.$refs 來獲取元素和組件、Vue 組件中 data 和 props 的區別)

下一篇:HTML5期末大作業:關于旅游景點介紹的HTML網頁設計——榆林子州 8頁 (含畢設論文9000字) 建議收藏...

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more