TypeScript_线性结构-数组-栈结结构

news2025/4/8 20:29:29

数据结构与算法

面试经典 150 题

编程的最终目的只有一个:对数据进行操作和处理

  • 术之尽头炁体源流
  • 编程尽头数据结构

数据结构与算法的本质就是一门专门研究数据如何组织、存储和操作的科目

系统、语言、框架源码随处可见数据结构与算法

  • 无论是操作系统(Windows、Mac OS)本身,还是我们所使用的编程语言(JavaScript、Java、C++、Python等等)还是我们在平时应用程序中用到的框架(Vue、React、Spring、Flask等等),它们的底层实现到处都是数据结构与算法,所以你要想学习一些底层的知识或者某一个框架的源码(比如 Vue、React的源码)是必须要掌握数据结构与算法的
  • 以前端为例:框架中大量使用到了栈结构、队列结构等来解决问题(比如之前框架源码时经常看到这些数据结构,Vue 源码、React 源码、Webpack 源码中可以看到队列、栈结构、队列结构等来解决问题,Webpack 中还可以看到很多 Graph 图结构)
  • 实现语言或者引擎本身也需要大量的数据结构:哈希表结构、队列结构(微任务队列、宏任务队列),前端无处不在的数据结构:DOM Tree(树结构)、AST(抽象语法树)

因为对于很多企业来说,想要短时间考察一个人的能力以及未来的潜力,数据结构与算法是非常重要的指标,也会成为它们的硬性条件

  • 对于可以将数据结构与算法掌握很好的开发人员来说,通常对于业务的把握肯定是没有问题的
  • 并且对于系统的设计也会更加合理,可以写出更加高效的代码

数据结构

  • 数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出————《数据结构、算法与应用》
  • 数据结构是 ADT(抽象数据类型 Abstract Data Type)的物理实现————《数据结构与算法分析》
  • 数据结构(data structure)是计算机中存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来最优效率的算法————中文维基百科

图书摆放规则

  • 随便放
    • 插入操作:哪里有空放哪里,一步到位
    • 查找操作:找某本书,累死…
  • 按照书名的拼音字母顺序摆放
    • 插入操作:新进一本《阿Q正传》、《理想国》,按照字母顺序找到位置,插入
    • 查找操作:二分查找法
  • 把书架划分成几个区域,按照类别存放,类别中按照字母顺序
    • 插入操作:先定类别,二分查找确定位置,移出空位
    • 查找操作:先定类别,再二分查找

常见数据结构

  • 数组(Array)
  • 栈结构(Stack)
  • 队列(Queue)
  • 链表(LinkedList)
  • 图结构(Graph)
  • 散列表(Hash)
  • 树结构(Tree)
  • 堆结构(Heap)

算法

解决问题的过程中,不仅仅数据的存储方式会影响效率,算法的优劣也会影响效率

算法

  • 一个有限的指令集,每条指令的描述不依赖于语言
  • 接受一些输入(有些情况下不需要输入)
  • 产生输出
  • 一定在有限步骤之后终止

生活中的算法

  • 找出线缆出题的地方:

    • 假如上海和杭州之间有一条高架线,高架线长度是 100000 米,有一天高架线中有其中一米出现了故障
    • 请你想出一种算法,可以快速定位到出问题的地方
  • 线性查找:

    • 从上海的起点开始一米一米的排查,最终一定能找到出问题的线段
    • 但是如果线段在另一头,我们需要排查 100000 次,这是最坏的情况,平均需要 50000 次
  • 二分查找:

    • 从中间位置开始排查,看一下问题出在上海到中间位置,还是中间到杭州的位置
    • 查找对应的问题后,再从中间位置分开,重新锁定一般的路程
    • 最坏的情况,需要多少次可以排查完呢?最坏的情况是20次就可以找到出问题的地方
    • 怎么计算出来的呢?log(100000,2),以 2 为底,100000 的对数 ≈ 20
  • 结论:

    你会发现,解决问题的办法有很多,但是好的算法对比于差的算法,效率天囊之别

线性结构

线性结构(Linear List)是由 n(n>=0)个数据元素(结点)a[0]、a[1]、a[2]…a[n-1]组成的有限序列

  • 数据元素的个数 n 定义为表的长度=list.length()list.length()=0 时称为空表)
  • 将非空的线性表(n>=1)记作:(a[0]、a[1]、a[2]…a[n-1])
  • 数据元素 a[i](0<=i<=n-1)只是个抽象符号,其具体含义在不同情况下可以不同

上面是维基百科对于线性结构的定义,有一点点抽象,其实我们只需要记住几个常见的线性结构即可

  • 数据结构(Array)
  • 栈结构(Stack)
  • 队列结构(Queue)
  • 链表结构(LinkedList)

数组

  • 几乎每种编程语言都会提供一种原生数据结构
  • 并且我们可以借助数组结构来实现其他的数据结构,比如栈(Stack)、队列(Queue)、堆(Heap)

通常数组的内存是连续的,所以数组在知道下标值的情况下,访问效率是非常高的

在这里插入图片描述

  • 栈也是一种非常常见的数据结构,并且在程序中的应用非常广泛
  • 数组
    • 我们知道数组是一种 线性结构,并且可以在数组的 任意位置 插入和删除数据
    • 但是有时候,我们为了实现某些功能,必须对这种 任意性 加以 限制
    • 栈和队列 就是比较常见的受限的线性结构

在这里插入图片描述

栈(Stack),它是一种受限的数据结构,后进先出(LIFO)

  • 其限制是仅允许在 表的一端 进行插入和删除运算。这一端被称为 栈顶,相对地,把另一端称为 栈底
  • LIFO(last in first out)表示就是后进入的元素,第一个弹出栈空间。类似于自动餐托盘,最后放上的托盘,往往先把它拿出去使用
  • 向一个栈插入新元素又称作 进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为栈顶元素
  • 从一个栈删除元素又称作出 栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素

题目

有六个元素 6、5、4、3、2、1 的顺序进栈,问下面哪一个不是合法的出栈序列?

  • 5、4、3、6、1、2
  • 4、5、3、2、1、6
  • 3、4、6、5、2、1 ×
  • 2、3、4、1、5、6

实现栈结构有两种比较常见的方式:

  • 基于数组实现
  • 基于链表实现

实现栈

  • 创建一个 Stack,用户创建栈的类,可以顶一个泛型类
  • 在构造函数中,定义了一个变量(数组类型),这个变量可以用于保存当前栈对象中所有的元素
  • 之后不论是压栈操作还是出栈操作,都是从数组中添加和删除元素
class Stack<T> {
  private data: T[] = []
}

在 node 环境下执行 ts 代码

$ npm i -g ts-node

栈的操作

  • push(element):添加一个新元素到栈顶位置
  • pop():移除栈顶的元素,同时返回被移除的元素
  • peek():返回栈顶的元素,不会对栈做任何修改
  • isEmpty():如果栈里面没有任何元素就返回 true,否则返回 false
  • size():返回栈里的元素个数。这个方法和数组的 length 属性很类似
class ArrayStack {
  private data: any[] = []
  // push:将一个元素压入栈中
  push(element: any) {
    this.data.push(element)
  }
  // pop:将栈顶元素弹出栈(返回出去,并且从栈顶移除)
  pop(): any {
    return this.data.pop()
  }
  // peek:看一眼栈顶元素,但是不进行任何操作
  peek(): any {
    return this.data[this.data.length - 1]
  }
  // isEmpty:判断栈是否为空
  isEmpty(): boolean {
    return this.data.length === 0
  }
  // size:返回栈的数据个数
  size(): number {
    return this.data.length
  }
}

const stack1 = new ArrayStack()
stack1.push('aaa')
stack1.push('bbb')

console.log(stack1.peek())
console.log(stack1.pop())
console.log(stack1.pop())
console.log(stack1.isEmpty())
console.log(stack1.size())

泛型重构栈

class ArrayStack<T> {
  private data: T[] = []
  push(element: T) {
    this.data.push(element)
  }
  pop(): T | undefined {
    return this.data.pop()
  }
  peek(): T | undefined {
    return this.data[this.data.length - 1]
  }
  isEmpty(): boolean {
    return this.data.length === 0
  }
  size(): number {
    return this.data.length
  }
}

接口抽离和封装

import { IStack } from './IStack'

class LinkedStack<T> implements IStack<T> {
  private data: T[] = []
  push(element: T) {
    this.data.push(element)
  }
  pop() {
    return this.data.pop()
  }
  peek() {
    return this.data[this.data.length - 1]
  }
  isEmpty() {
    return this.data.length === 0
  }
  size() {
    return this.data.length
  }
}

使用接口定义栈的结构

interface IStack<T> {
  push(element: T): void
  pop(): T | undefined
  peek(): T | undefined
  isEmpty(): boolean
  size(): number
}

export { IStack }

十进制转二进制

为什么需要十进制转二进制

  • 现实生活中,我们主要使用十进制
  • 在计算机科学中,二进制非常重要,因为计算机里所有内容都是二进制数字表示的(0 和 1)
  • 没有十进制和二进制相互转换的能力,与计算机交流就很困难
  • 转换二进制是计算机科学和编程领域中经常使用的算法

如何实现十进制转二进制

  • 要把十进制转换成二进制,我们可以将十进制数字和 2 整除(二进制是满二进一),直到结果是 0 为止
import ArrayStack from './stack_refactor'

function decimalToBinary(decimal: number): string {
  // 1.创建一个栈,用于存放余数
  const stack = new ArrayStack<number>()

  // 2.使用循环 while(不确定次数,只知道循环结束条件) for(知道循环的次数)
  while (decimal > 0) {
    const result = decimal % 2
    stack.push(result)
    decimal = Math.floor(decimal / 2)
  }

  // 3.所有的余数都已经放在 stack 中,依次取出即可
  let binary = ''
  while (!stack.isEmpty()) {
    binary += stack.pop()
  }
  return binary
}

有效括号

20.有效括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合
  • 左括号必须以正确的顺序闭合
  • 每个右括号都有一个对应的相同类型的左括号
import ArrayStack from './stack_refactor'

function isValid(s: string): boolean {
  // 创建栈结构
  const stack = new ArrayStack<string>()
  // 2.遍历s中所有的括号
  for (let i = 0; i < s.length; i++) {
    const c = s[i]
    switch (c) {
      case '(':
        stack.push(')')
        break
      case '{':
        stack.push('}')
        break
      case '[':
        stack.push(']')
        break
      default:
        if (c !== stack.pop()) return false
        break
    }
  }
  return stack.isEmpty()
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/961121.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

openlayers-16-添加一组轨迹动画

实现一组动画&#xff0c;即根据一组只有起止点坐标的线段&#xff0c;实现点在这些线段上较为平滑的移动&#xff0c;移动速度和平滑程度均可控制。 下面的代码仅作为思路参考&#xff0c;还欠缺很多细节&#xff0c;比如在进行插值计算时&#xff0c;还需要判断经纬度坐标差&…

RocketMQ(消息中间件)

目录 一、为什么会出现消息中间件&#xff1f; 二、消息中间件是干嘛的&#xff1f; 三、应用解耦 四、流量削峰 五、异步处理 1.串行方式&#xff1a; 2.并行方式&#xff1a; 3.引入消息队列&#xff1a; 六、RocketMQ的架构及概念 一、为什么会出现消息中间件&#…

opencv-人脸识别

对https://blog.csdn.net/weixin_46291251/article/details/117996591这哥们代码的一些修改 import cv2 import numpy as np import os import shutil import threading import tkinter as tk from PIL import Image, ImageTkchoice 0# 首先读取config文件&#xff0c;第一行…

国内8个能用AI赚钱的在线兼职渠道整理

hi&#xff0c;同学们&#xff0c;我是赤辰&#xff0c;本期是赤辰第3篇AI工具类教程&#xff0c;文章底部准备了粉丝福利&#xff0c;看完可以领取&#xff01;即将迎来新学期了&#xff0c;今天就来聊聊学生党如何应用AI技能通过兼职&#xff0c;赚取生活费&#xff0c;这里指…

使用HTTPS模式建立高效爬虫IP服务器详细步骤

嘿&#xff0c;各位爬虫小伙伴们&#xff01;想要自己建立一个高效的爬虫IP服务器吗&#xff1f;今天我就来分享一个简单而强大的解决方案——使用HTTPS模式建立工具&#xff01;本文将为你提供详细的操作步骤和代码示例&#xff0c;让你快速上手&#xff0c;轻松建立自己的爬虫…

【枚举区间+线段树】CF Ehu 152 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 感觉是个套路题 对区间计数&#xff0c;按照CF惯用套路&#xff0c;枚举其中一个端点&#xff0c;对另一个端点计数 对于这道题&#xff0c;枚举右端点&#xff0c;对左端点计数 Code&#xff1a; #include &…

Form.Item创建自定义表单

一、概述 Antd是一个非常强大的UI组件库&#xff0c;里面的Form表单组件也基本能满足我们大多数场景。但是也有需要自定义表单的场景。 Vue2里我们使用v-model&#xff0c;结合子组件的model属性&#xff0c;来实现自定义组件的双向绑定。 Vue3里我们使用v-model&#xff0c;…

没有苹果开发者账号能否创建ios证书-最新

​ 目录 摘要&#xff1a; 引言&#xff1a; 步骤一&#xff1a; 步骤二&#xff1a; 步骤三&#xff1a; 步骤四&#xff1a; 步骤五&#xff1a; 总结&#xff1a; 摘要&#xff1a; 本文介绍了在没有Mac电脑的情况下&#xff0c;使用appuploader工具生成iOS证书和描…

高通QualComm、MTK耦合测频段工具和综测校准工具的自由定制 与工厂Mes对接、使用PowerMeter测量等

一.MTK耦合工具V1.3 20220409 MTK芯片 1.逻辑&#xff1a; 打开软件&#xff0c;扫码SN&#xff0c;自动连接&#xff0c;连接成功后 1).开启强发&#xff08;强发参数 LTE频段 1、3、5、7、28&#xff09; 2).读测量值 3).结果判定&#xff…

【计算机组成 课程笔记】3.2 算数运算和逻辑运算的硬件实现

课程链接&#xff1a; 计算机组成_北京大学_中国大学MOOC(慕课) 3 - 2 - 302-门电路的基本原理&#xff08;11-39--&#xff09;_哔哩哔哩_bilibili 现代计算机的CPU和其他很多功能部件都是基于晶体管的集成电路&#xff0c;想要了解计算机组成的基本原理&#xff0c;还是需要有…

电脑报错提示xinput1_3.dll缺失怎么办?xinput1_3.dll丢失的简单恢复方案

今天&#xff0c;我将为大家分享一个与我们日常工作息息相关的话题——xinput1_3.dll丢失的4种解决方法。在我们的日常工作和生活中&#xff0c;电脑出现问题是常有的事&#xff0c;而xinput1_3.dll丢失则是其中较为常见的一种问题。那么&#xff0c;什么是xinput1_3.dll?它为…

C盘扩容遇到的问题(BitLocker解密、)

120G的C盘不知不觉的就满了&#xff0c;忍了好久终于要动手了。 尽管电脑-管理--磁盘管理里可以进行磁盘大小调整&#xff0c;但由于各盘都在用&#xff0c;不能够连续调整&#xff0c;所以选用DiskGenius。 # DiskGenius调整分区大小遇到“您选择的分区不支持无损调整容量” …

undolog

一、原子性 ACID&#xff1a;通过undolog保证原子性 二、undolog 如何做 把回滚时所需的东西都给记下来&#xff1a; 1、插入一条记录时&#xff0c;至少要把这条记录的主键值记下来&#xff0c;回滚的时候只需要把这个主键值对应的记录删掉就好了。 2、删除了一条记录&…

10 行代码能做什么?

10 行代码能做什么&#xff1f; 写一串 SQL Join&#xff0c;统计全渠道市场营销的 ROI 用 JS 画个饼图&#xff0c;展示最有效的广告投放策略 用 Python 写段算法&#xff0c;分析销量骤降的原因是什么 …… 数据出错了&#xff0c;写个对数脚本 -_-|| AI 时代&#xff0c;…

AI图像行为分析算法 opencv

AI图像行为分析算法通过pythonopencv深度学习框架对现场操作行为进行全程实时分析&#xff0c;AI图像行为分析算法通过人工智能视觉能够准确判断出现场人员的作业行为是否符合SOP流程规定&#xff0c;并对违规操作行为进行自动抓拍告警。OpenCV是一个基于Apache2.0许可&#xf…

管理类联考——逻辑——汇总篇——知识点突破——形式逻辑——联言选言——定义

角度——本质定义 联言 联言命题是断定两种或两种以上事物情况同时存在的命题&#xff0c;用“A并且B”表示&#xff0c;逻辑符号为A ∧ B。 若“A ∧ B”为真&#xff0c;表明A是真的&#xff0c;同时B也是真的。 【定义】联言命题是表示若干判断同时成立的命题。 【刻画】…

Java与其他编程语言比较分析,编程语言选择与优点、缺点和适用场景详解

原文地址&#xff1a;Java与其他编程语言比较分析&#xff0c;编程语言选择与优点、缺点和适用场景详解 Java 擅长可移植性和可靠性&#xff0c;Python 擅长通用性和简单性&#xff0c;JavaScript 擅长 Web 开发&#xff0c;C 擅长性能&#xff0c;Go 擅长效率。网址:yii666.c…

网御星云-上网行为管理系统bottomframe.cgi接口存在SQL注入

一、免责声明&#xff1a; 本次文章仅限个人学习使用&#xff0c;如有非法用途均与作者无关&#xff0c;且行且珍惜&#xff1b;由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;公众号望雪阁及作者不为此…

OS 内存使用和分段

磁盘很大但是内存很小&#xff0c;当进程一堵塞的时候&#xff0c;就把进程一放入磁盘&#xff0c;然后进程二进去。进程三睡眠的时候在把二和三交换&#xff0c;所以载入之后重定位不太行 GDT是整个操作系统的段表&#xff0c;多个进程的 LDT时某个进程的段表

SpringBoot 博客网站

SpringBoot 博客网站 系统功能 登录注册 博客列表展示 搜索 分类 个人中心 文章分类管理 我的文章管理 发布文章 开发环境和技术 开发语言&#xff1a;Java 使用框架: SpringBoot jpa H2 Spring Boot是一个用于构建Java应用程序的开源框架&#xff0c;它是Spring框架的一…