Typescript数据结构与算法(01) | 线性结构

62 阅读4分钟

写在前面: 写这系列文章的原因是为了督促自己学习数据结构与算法,顺便养成写文章的习惯。这系列文章的参考为coderwhy老师的typescript数据结构与算法,感谢coderwhy老师的辛苦付出。图片和文字部分出自coderwhy老师的ppt和视频语录

希望能写下去,不要烂尾了

01.目录结构

  1. 线性结构:数组,栈,队列,链表
  2. 哈希表
  3. 树结构
  4. 图结构
  5. 高阶链表:循环链表,双向链表
  6. 堆结构
  7. 高阶队列:双端队列
  8. 高阶树:平衡二叉树
  9. 排序算法
  10. 动态规划

目前规划这么多,后续可能改变,一切以实际为准

那我们就开始今天的学习吧!

02.线性结构

2.1 什么是线性结构

线性结构(英語: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)只是个抽象符号,其具体含义在不同情况下可以不同。

常见的线性结构有数组,栈,队列,链表,我们今天只谈数组结构和栈结构

03.数组结构

3.1 什么是数组

  • 数组是一种很重要的数据结构,在许多语言中都会内置,并且我们可以通过数组来实现其他的数据结构,比如栈,队列,堆。
  • 我们可以创建一个最简单的数组,看看它的表现
const Array1 = [1, 2, 3, 4, 5]
console.log(Array1)

image.png

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

image.png

关于数组,我们知道这些就够了,接下来我们讲讲栈

04.栈结构

众所周知的是,在JS中,它的内存分为三种类型:代码空间,栈空间,堆空间。

基本数据类型储存在栈空间中,引用数据类型储存在堆空间中。

那我们为什么有了数组结构这种可以在任意位置插入和删除数据的数据结构后,还要栈结构呢,因为这种任意性有时会带来很大的负担。比如当数组中很多数据时,我们在其中插入一条数据,会导致后面所有的数据向后平移一个下标,成本很高,所以我们必须加以限制

4.1 什么是栈结构

我们对栈做了什么限制呢?

我们只能对栈的一端进行插入和运算操作,这一端被称为栈顶,相反的,另一端被称为栈底。栈遵循后进先出的原则,这和队列结构的先进先出是不同的,队列结构我们之后会讲到。

后进先出的原则即,后进入的元素第一个弹出栈空间。我们可以画个图展示一下

image.png

我们做个题加深一下印象:

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

A. 5 4 3 6 1 2

B. 4 5 3 2 1 6

C. 3 4 6 5 2 1

D. 2 3 4 1 5 6

我们逐个分析一下:

A:65进栈,5出栈,4进栈出栈,3进栈出栈,6出栈,21依次进栈,12依次出栈

B:654进栈,45出栈,3进栈出栈,2进栈出栈,1进栈出栈,6出栈

C:6543进栈,34依次出栈,此时6必须在5的后边出栈,不能再5的前面出栈,所以这题选C

大家可以自行分析一下D

4.2 用TS实现栈结构

栈可以用数组和链表来实现,因为链表我们还没学,所以我们使用数组

再实现栈之前我们先来学习一下,栈有哪些操作

  • push:添加一个元素到栈顶
  • pop:移除栈顶元素,同时返回被移除的元素
  • peek:返回栈顶的元素,不对栈做任何修改
  • isEmpty:查看栈是否为空,如果为空返回true,否则返回false
  • size:返回栈中的元素个数

实现代码:

我们首先先封装一个类然后在类中定义一个数组用于储存元素,之后不论什么操作都是对数组进行操作

class MyStack<T> {
  private data: T[] = []

  // 实现栈中相关的操作方法
  // push方法: 将一个元素压入到栈中
  push(element: T): void {
    this.data.push(element)
  }

  // pop方法: 将栈顶的元素弹出栈(返回出去, 并且从栈顶移除掉)
  pop(): T | undefined {
    return this.data.pop()
  }

  // peek方法: 看一眼栈顶元素, 但是不进行任何的操作
  peek(): T | undefined {
    return this.data[this.data.length - 1]
  }

  // isEmpty: 判断栈是否为空
  isEmpty(): boolean {
    return this.data.length === 0
  }

  // 返回栈的数据个数
  size(): number {
    return this.data.length
  }
}

export default MyStack