Node.js数据结构基础

栈 (先进后出)

实现栈的基础功能

  • push
  • pop
  • top
  • size
  • clear
class Stack {
    constructor() {
        this.data = [];
        this.count = 0;
    }
    push(value) {
        this.data[this.count++] = value;
        return 'success';
    }
    pop() {
        if (this.count <= 0) return 'no data';
        let temp = this.data[this.count - 1];
        delete this.data[--this.count];
        return temp;
    }
    top() {
        if (this.count <= 0) return 'no data';
        return this.data[this.count - 1];
    }
    size() {
        return this.count;
    }
    clear(){
        this.data = [];
        this.length = 0;
    }
}
const s = new Stack();

栈的应用

力扣题目 最小栈

题目描述:
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack

实现思路:采用两个栈,一个用于存储所有数据,一个用于存储最小数据的内容

class MinStack {
    constructor() {
        // 用于存储所有数据
        this.stackA = [];
        this.countA = 0;
        // 用于记录最小数据
        this.stackB = [];
        this.countB = 0;
    }
    push(val) {
        this.stackA[this.countA++] = val;
        if (this.countB === 0 || this.stackB[this.countB - 1] >= val) {
            this.stackB[this.countB++] = val;
        }
    }
    pop() {
        if (this.countA <= 0) return -1;
        if (this.stackB[this.countB - 1] === this.stackA[this.countA - 1]) {
            delete this.stackB[--this.countB];
        }
        const temp = this.stackA[this.countA - 1];
        delete this.stackA[--this.countA];
        return temp;
    }
    top() {
        if (this.countA <= 0) return -1;
        return this.stackA[this.countA - 1];
    }
    getMin() {
        if (this.countB <= 0) return -1;
        return this.stackB[this.countB - 1];
    }
}

队列 (先进先出)

队列基础功能

  • enQueue
  • deQueue
  • top
  • size
  • clear
'use strict';
class Queue{
    constructor(){
        this.queue = {};
        this.count = 0; // 数量
        this.head = 0; // 头部位置
    }
    enQueue(val){
        this.queue[this.count++] = val;
    }
    deQueue(){
        if(this.count-this.head<=0)return 'no data';
        const temp = this.queue[this.head];
        delete this.queue[this.head++];
        this.count--;
        return temp
    }
    top(){
        if(this.count-this.head<=0)return 'no data';
        return this.queue[this.head];
    }
    size(){
        return this.count-this.head;
    }
    clear(){
        this.head = 0;
        this.count = 0;
        this.queue = {};
    }
}

队列的应用

题目描述:
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof
实现:

class MaxQueue {
    constructor() {
        this.queue = {};
        this.doubleQueue = {};
        this.headQ = this.countQ = this.headD = this.countD = 0;
    }
    push_back(val) {
        this.queue[this.countQ++] = val;
        while (this.countD - this.headD > 0 && this.doubleQueue[this.countD - 1] < val) {
            delete this.doubleQueue[--this.countD];
        }
        this.doubleQueue[this.countD++] = val;
    }
    pop_front() {
        if (this.countD - this.headD <= 0) return -1;
        const temp = this.queue[this.headQ];
        delete this.queue[this.headQ++];
        if(temp === this.doubleQueue[this.headD]){
            delete this.doubleQueue[this.headD++];
        }
        return temp;
    }
    max_value(){
        if (this.countD - this.headD <= 0) return -1;
        return this.doubleQueue[this.headD];
    }
}

题目描述:
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sliding-window-maximum

程序:

'use strict';
// 请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

// 若队列为空,pop_front 和 max_value 需要返回 -1

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
//  https://leetcode-cn.com/problems/sliding-window-maximum/
var maxSlidingWindow = function (nums, k) {

    if (k <= 1) return nums;
    const queue = {};
    let count = 0;
    let head = 0;
    const result = [];
    for (let i = 0; i < k; i++) {
        if(count - head === 0)queue[count++] = nums[i];
        else{
            while(count - head !== 0 && queue[count-1]<nums[i]){
                delete queue[--count];
            }
            queue[count++] = nums[i];
        }
    }
    
    result.push(queue[head]);
    for(let j=k;j<nums.length;j++){
        // 出队
        if(queue[head] === nums[j-k]){
            delete queue[head++];
        }
        // 入队
        while(count - head !== 0 && queue[count-1]<nums[j]){
            delete queue[--count];
        }
        queue[count++] = nums[j];        
        result.push(queue[head]);
    }
    return result;
};

链表

基础功能

  • addAtTail
  • addAtHead
  • get (根据索引获取数据)
  • addIndex
  • reverseList (迭代法)
  • reverseList_head (头插法)
  • reverseList_d (递归)
  • print
'use strict';

// 链表的概念 : 链表是有序的数据结构
// 数组在内存中占用一段连续的内存
// 数组添加、移除会导致后续元素位移和性能开销大
// 链表和数组的区别
// 场景:获取、修改元素时,数组效率高。
// 添加、删除元素时,链表效率高

// 链表的实现方式
class LinkedNode {
    constructor(value) {
        this.value = value;
        this.next = null;
    }
}
class LinkedList {
    constructor() {
        this.head = null;
        this.count = 0;
    }
    addAtTail(value) {
        const node = new LinkedNode(value);
        if (this.count === 0) {
            this.head = node;
        } else {
            let cur = this.head;
            while (cur.next !== null) {
                cur = cur.next;
            }
            cur.next = node;
        }
        this.count++;
    }
    addAtHead(value) {
        const node = new LinkedNode(value);
        if (this.count === 0) {
            this.head = node;
        } else {
            node.next = this.head;
            this.head = node;
        }
        this.count++;
    }
    get(index) {
        if (this.count === 0 || index < 0 || index >= this.count) return;
        let cur = this.head;
        for (let i = 0; i < index; i++) {
            cur = cur.next;
        }
        return cur.value;
    }
    // 根据索引添加节点
    addIndex(value, index = 0) {
        if (index > this.count) return '超出索引';
        index = index < 1 ? 0 : index;
        const node = new LinkedNode(value);
        if (index === 0) {
            node.next = this.head;
            this.head = node;
        } else {
            let cur = this.head;
            for (let i = 0; i < index - 1; i++) {
                cur = cur.next;
            }
            let pre = cur;
            node.next = cur.next;
            pre.next = node;
        }
        this.count++;
    }
    // 迭代法
    reverseList() {
        // 申明变量记录 pre next
        let pre = null;
        let cur = this.head;
        while (cur) {
            const next = cur.next;// 保存当前节点的下一个节点
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        this.head = pre;
    }
    // 头插法
    reverseList_head() {
        if (!this.head || !this.head.next) return;
        let cur = this.head;
        let back = null;
        while (cur) {
            let temp = cur;
            cur = cur.next;
            temp.next = back;
            back = temp;
        }
        this.head = back;
    }
    // 递归操作
    reverseList_d(head){
        if(head === null && head.next === null) return head;
        const newHead = reverseList_d(head.next);
        // 5->4->3->2->1->null
        // 第一次执行的节点是 倒数第二个数据 此时 newHead = 1 head = 2
        head.next.next = head;
        head.next = null;
        return newHead;
    }
    print() {
        let h = this.head;
        while (h) {
            console.log(h.value);
            h = h.next;
        }
    }
}


const l = new LinkedList();
l.addAtTail(1);
l.addAtTail(2);
l.addAtTail(3);
// l.print();
l.reverseList();
l.print();
l.reverseList_head();
l.print()

二叉树

题目:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

  • 二叉树的前序遍历(递归)
var preorderTraversal = function (root) {
    const arr = [];
    const r = root => {
        if (!root) return;
        arr.push(root.val);
        r(root.left);
        r(root.right);
    }
    r(root);
    return arr;
};
  • 二叉树的前序遍历的迭代法
var preorderTraversal = function (root) {
    const arr = [];
    const stack = [];
    while (root || stack.length>0) {
        while (root) {
            arr.push(root.val);
            stack.push(root.right);
            root = root.left;
        }
        root = stack.pop();
    }
    return arr;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值