JavaScript 数据结构

151 阅读3分钟

数据结构

队列,栈,链表,哈希表,树

队列 queue

先进先出的数组 fifo
first in first out

餐厅叫号网页

选用队列作为数据结构,queue.push入队,queue.shift出队

HTML
<head>
    <title>队列示例</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <div id="screen"></div> 
    <div class="actions"> 
      <button id="createNumber">取号</button>
      <button id="callNumber">叫号</button>
    </div>
    <div>
      当前号码<span id="newNumber"></span>
    </div>
    <div>
      当前队列<span id="queue"></span>
    </div>
    <script src="./main.js"></script>
</body>

CSS
#screen{
    border: 1px solid black;
    width: 200px;
    height: 200px;
}

JS                                                                             
const divScreen = document.querySelector('#screen');
const btnCreateNumber = document.querySelector('#createNumber');
const btnCallNumber = document.querySelector('#callNumber');
const spanNewNumber = document.querySelector('#newNumber');
const spanQueue = document.querySelector('#queue');

let n = 0;  
let queue = [];

btnCreateNumber.onclick = () => {                                              
    n += 1;                                                                    
    queue.push(n);
    //queue.push.call(queue,n);
    spanNewNumber.innerText = n;
    spanQueue.innerText = JSON.stringify(queue);
};

btnCallNumber.onclick = () => {
    if (queue.length === 0) {
        return;
    }
    const m = queue.shift();      
    //const m = queue.shift.call(queue);
    divScreen.innerText = `请${m}号就餐`;
    spanQueue.innerText = JSON.stringify(queue);
}

栈 stack

后进先出的数组 lifo
last in first out

压栈出栈的过程就是后入先出

function f1(){let a = 1; return a+f2()}
function f2(){let b = 2; return b+f3()}
function f3(){let c = 3; return c}
f1()

JS函数的调用栈call stack就是一个栈
f1调用了f2,f2又调用了f3,那么f3结束后应该回到f2,f2结束后应该回到f1

压栈是push
弹栈是pop,弹出最上面的,把这个值返回给你

链表 Linked List

一个链一个,用一个地址指向下一个对象

JS原型链

let array = [1,2,3]
array.__proto__ === Array.prototype
Array.prototype.__proto__ ===Object.prototype

从这个角度看JS原型链,就是链表;JS的每个对象就是链表

原型链断开(没有数组的原型了)
array.__proto__=Object.prototype

链表的增删改查

一个节点在JS里用一个对象表示{}

节点有2个属性
data          data:value
next          next:null 默认值是空

const createList = value => {
    return createNode(value);
};

创建链表
const appendList = (list, value) => {
    const node = createNode(value);
    let x = list;                                                    
    while (x.next) {              
      x = x.next;                                               
    }
    x.next = node;
    return node;
}

添加节点
const createNode = value => {
    return {
      data: value,
      next: null
    };
};

删除节点
const removeFromList = (list, node) => {
    let x = list;
    let p = null;
    while (x !== node) {
        p = x;
        x = x.next;
    };
    p.next = x.next;                                           
};

const travelList = (list, fn) => {                     
    let x = list;                                                     
    while (x !== null) {
        fn(x);
        x = x.next;
    }
};

const list = createList(10);          创建一个链表,节点内容是10
const node2 = appendList(list, 20);   返回到新增加的节点,给list一个新的值20

双向链表
每个节点有一个previous 指向上一个节点
每一个有指向上一个节点和下一个节点的链表叫双向链表

循环链表
最后一个节点的next指向头节点

哈希表

key value pairs

读取哈希表

假设:哈希表hash里有1万对key-value
例如:name:'frank',age:18`......
如何读取hash['xxx']速度最快

不做任何优化,hash['xxx']需要遍历所有的key

对key排序,使用2分查找

用字符串对应的ASCll数字做索引
对索引做除法,取余数,有冲突就顺延

key越多,读取速度越慢

树 tree

一个链多个,data,children

创建树

const createTree = value => {
    return {
      data: value,
      children: null,
      parent: null
    };
};

const addChild = (node, value) => {
    const newNode = {
        data: value,
        children: null,
        parent: node
    };
    node.children = node.children || [];
    node.children.push(newNode);
    return newNode;
};
 
 遍历树的分支,看要删除的是否存在
const travel = (tree, fn) => {
    fn(tree);
    if (!tree.children) {
      return;
    };
    for (let i = 0; i < tree.children.length; i++) {
        travel(tree.children[i], fn);
    }
};
 
 删除节点(把地址也删除)
const removeNode = (tree, node) => {
    const siblings = node.parent.children;
    let index = 0;
    for (let i = 0; i < siblings.length; i++) {
        if (siblings[i] === node) {
            index = i;
        }
    }
    siblings.splice(index, 1);
};

const tree = createTree(10);        创建树
const node2 = addChild(tree, 20);   创建节点
addChild(tree, 30);                 新增树
addChild(node2, 201);               新增节点