TypeScript 中数据结构的实现方式与性能对比

阅读时长 15 分钟读完

前言

TypeScript 是 JavaScript 的超集,在 JavaScript 的基础上增加了强类型、接口、类和模块等特性。相比 JavaScript,TypeScript 支持静态类型检查,可以帮助我们在编写代码时提前捕获错误,提高代码的可读性和可维护性。在 TypeScript 中,我们可以使用面向对象编程的思想来实现各种数据结构,包括数组、链表、栈、队列、堆、二叉树等。本文将介绍 TypeScript 中常用的几种数据结构的实现方式与性能对比。

数组

数组是最常用的数据结构之一,它可以存储一组数据,并提供基本的增删改查操作。在 TypeScript 中,数组的定义和使用方法与 JavaScript 基本相同,只是我们可以使用泛型来限定数组中元素的类型。下面是一个示例代码:

-- -------------------- ---- -------
-- ---- ------ -----
--- ---- -------- - --- -- ---

-- ---- ------ -----
--- ------- ------------- - --------- ---------

-- ------
------ - --

-- ------
----------

-- ---------
------------

-- ----
------------------ -- -
  ------------------
---

数组在内存中以连续的方式存储,可以快速访问数组的任意位置,但是在使用 push 和 pop 等操作时,可能需要移动大量元素,导致性能下降。如果需要对数组进行频繁的添加和删除操作,建议使用链表代替数组。

链表

链表是另一种常用的数据结构,它由一系列的节点组成,每个节点包含了数据和下一个节点的地址。在 TypeScript 中我们可以使用类来定义节点和链表,并实现基本的增删改查操作。下面是一个示例代码:

-- -------------------- ---- -------
-- -------
----- ----------------- -
  ------ ----- --
  ------ ----- ----------------- - -----

  ----------------- -- ----- ----------------- - ---- - ----- -
    --------- - -----
    --------- - -----
  -
-

-- -------
----- ------------- -
  ------- ----- ----------------- - -----
  ------- ----- ----------------- - -----

  ------------- -
    --------- - -----
    --------- - -----
  -

  -- -----------
  ------ --------- --- ---- -
    ----- ---- - --- ------------------------

    -- ---------- --- ----- -
      --------- - -----
      --------- - -----
    - ---- -
      --------------- - -----
      --------- - -----
    -
  -

  -- -----------
  ------ ------------ -- ------ -------- ---- -
    -- ------ - -- -
      ----- --- ------------ --- -- ------ -----------
    -

    ----- ---- - --- ------------------------
    --- ----- ----------------- - ---- - -----
    --- -------- ----------------- - ---- - ----------

    --- ---- - - -- ------- --- ---- -- - - ------ ---- -
      ---- - --------
      ------- - -------------
    -

    -- ----- --- ----- -
      --------- - -----
    - ---- -
      --------- - -----
    -

    --------- - --------

    -- -------- --- ----- -
      --------- - -----
    -
  -

  -- -----------
  ------ ------------- -------- - - --------- -
    -- ------ - -- -
      ----- --- ------------ --- -- ------ -----------
    -

    --- ----- ----------------- - ---- - -----
    --- -------- ----------------- - ---- - ----------

    --- ---- - - -- ------- --- ---- -- - - ------ ---- -
      ---- - --------
      ------- - -------------
    -

    -- -------- --- ----- -
      ------ ----------
    -

    -- ----- --- ----- -
      --------- - -------------
    - ---- -
      --------- - -------------
    -

    -- ------------- --- ----- -
      --------- - -----
    -

    ------ -------------
  -

  -- ----------
  ------ ---------- -------- - - --------- -
    -- ------ - -- -
      ----- --- ------------ --- -- ------ -----------
    -

    --- -------- ----------------- - ---- - ----------

    --- ---- - - -- ------- --- ---- -- - - ------ ---- -
      ------- - -------------
    -

    ------ --------------
  -

  -- --------
  ------ ---------- ------- -
    ------ --------- --- -----
  -

  -- ------
  ------ --------- ------ -
    --- ------ - --
    --- -------- ----------------- - ---- - ----------

    ----- -------- --- ----- -
      ---------
      ------- - -------------
    -

    ------ -------
  -

  -- --------
  ------ ---------- --- -
    ----- --- - ---
    --- -------- ----------------- - ---- - ----------

    ----- -------- --- ----- -
      -----------------------
      ------- - -------------
    -

    ------ ----
  -
-

-- ----
----- ---- - --- ---------------------
------------
------------
-------------- ---
---------------
----------------------------

链表在内存中不是连续存储的,每个节点只存储了下一个节点的地址,因此在添加和删除节点时,不需要移动其他节点,可以快速完成操作。但是在访问链表中的任意位置时,需要从头节点开始遍历,时间复杂度为 O(n),因此链表适用于需要频繁添加和删除节点,但不需要随机访问元素的场景。如果需要随机访问元素,建议使用数组。

栈是一种后进先出的数据结构,即最后放入的元素最先弹出。在 TypeScript 中我们可以使用数组或链表来实现栈,栈的基本操作包括 push、pop、peek 和 isEmpty。下面是一个使用数组实现栈的示例代码:

-- -------------------- ---- -------
----- -------- -
  ------- ------ ----

  ------------- -
    ---------- - ---
  -

  -- --
  ------ ---------- --- ---- -
    ----------------------
  -

  -- --
  ------ ------ - - --------- -
    ------ -----------------
  -

  -- ------
  ------ ------- - - --------- -
    ------ ---------------------------- - ---
  -

  -- -------
  ------ ---------- ------- -
    ------ ----------------- --- --
  -
-

-- ---
----- ----- - --- ----------------
--------------
--------------
--------------
-------------------------- -- -- -
------------------------- -- -- -
------------------------- -- -- -
----------------------------- -- -- -----

在使用数组实现栈时,由于数组的长度可能会发生变化,导致内存空间的重新分配和数据的搬移,因此在添加和删除元素时,复杂度为 O(1) 和 O(n)。在使用链表实现栈时,由于链表的添加和删除操作时间复杂度均为 O(1),因此链表实现的栈更加效率高。

队列

队列是一种先进先出的数据结构,即最先放入的元素最先弹出。在 TypeScript 中我们可以使用数组或链表来实现队列,队列的基本操作包括 enqueue、dequeue、peek 和 isEmpty。下面是一个使用数组实现队列的示例代码:

-- -------------------- ---- -------
----- -------- -
  ------- ------ ----

  ------------- -
    ---------- - ---
  -

  -- --
  ------ ------------- --- ---- -
    ----------------------
  -

  -- --
  ------ ---------- - - --------- -
    ------ -------------------
  -

  -- ------
  ------ ------- - - --------- -
    ------ --------------
  -

  -- --------
  ------ ---------- ------- -
    ------ ----------------- --- --
  -
-

-- ----
----- ----- - --- ----------------
-----------------
-----------------
-----------------
-------------------------- -- -- -
----------------------------- -- -- -
----------------------------- -- -- -
----------------------------- -- -- -----

在使用数组实现队列时,由于数组的长度可能会发生变化,导致内存空间的重新分配和数据的搬移,因此在添加和删除元素时,复杂度为 O(1) 和 O(n)。在使用链表实现队列时,由于链表的添加和删除操作时间复杂度均为 O(1),因此链表实现的队列更加效率高。

堆是一种特殊的树形数据结构,它满足以下两个条件:

  • 堆是一个完全二叉树;
  • 堆中每个节点的值都大于或等于(或小于或等于)其子节点的值。

在 TypeScript 中,我们可以使用数组来表示堆,并通过数组下标计算节点之间的关系。堆主要有两种类型:最大堆和最小堆。最大堆的每个节点的值都大于或等于其子节点的值,最小堆的每个节点的值都小于或等于其子节点的值。下面是一个使用数组实现最大堆的示例代码:

-- -------------------- ---- -------
----- ---------- -
  ------- ------ --- - ---

  -- -----------
  ------- -------------- --- ------ -
    ------ -------------------------
  -

  -- ---------
  ------- -------------- -------- - - --------- -
    ------ ------------------
  -

  -- ----------
  ------- --------------- --- - - --------- -
    ----- ----- - --------------------
    ----- ----------- - ----------------- - -- - ---

    ------ --------------------------
  -

  -- -----------
  ------- ------------- --- - - --------- -
    ----- ----- - --------------------
    ----- --------- - - - ----- - --

    ------ ------------------------
  -

  -- -----------
  ------- -------------- --- - - --------- -
    ----- ----- - --------------------
    ----- ---------- - - - ----- - --

    ------ -------------------------
  -

  -- ----
  ------- ------------ --- ---- -
    --- ------- - -----
    --- ------ - ---------------------

    ----- ------- --- --------- -- ------ - -------- -
      ----- ----------- - ----------------------
      ----------------------- - --------
      ---------------------------------- - -------

      ------- - -------
      ------ - ------------------------
    -
  -

  -- ----
  ------- -------------- --- ---- -
    --- ------- - -----
    --- ---- - ----------------------
    --- ----- - -----------------------

    ----- -
      ----- --- --------- -- ---- - -------- --
      ------ --- --------- -- ----- - --------
    - -
      -- ------ --- --------- -- ---- - ------ -
        ----- --------- - --------------------

        ---------------------------------- - -----
        --------------------- - --------

        ------- - -----
      - ---- -
        ----- ---------- - ---------------------

        ---------------------------------- - ------
        ---------------------- - --------

        ------- - ------
      -

      ---- - ----------------------
      ----- - -----------------------
    -
  -

  -- --------
  ------ ------------ --- ---- -
    ----------------------
    ------------------
  -

  -- ------
  ------ ---------- - - --------- -
    -- ------------------ --- -- -
      ------ ----------
    -

    ----- ---- - --------------
    ----- ---- - ------------------

    -- ------------------ - -- -
      ------------- - -----
      --------------------
    -

    ------ -----
  -

  -- ------
  ------ ------- - - --------- -
    ------ ----------------- - - - ------------- - ----------
  -

  -- -------
  ------ ---------- ------- -
    ------ ----------------- --- --
  -
-

-- -----
----- ---- - --- ------------------
---------------
---------------
---------------
------------------------- -- -- -
---------------------------- -- -- -
---------------------------- -- -- -
---------------------------- -- -- -----

在使用数组实现堆时,由于数组的长度可能会发生变化,导致内存空间的重新分配和数据的搬移,因此在添加和删除元素时,复杂度为 O(log n) 和 O(log n)。在使用链表实现堆时,由于链表的添加和删除操作时间复杂度均为 O(1),因此链表实现的堆更加效率高。但是由于堆的操作主要是基于数组下标的计算,而链表是没有下标的,因此链表实现的堆需要额外的空间来存储节点之间的关系。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c1e02b314edc2684aba067

纠错
反馈