TypeScript算法专题 - [双链表1] - 双链的概念及其实现

简介: TypeScript算法专题 - [双链表1] - 双链的概念及其实现

TypeScript算法专题 -
[双链表1] 双链的概念及其实现


【导读】本文开始,练习双链表相关数据结构与算法。文中实现了一个简单的双链表。

1. 双链表的概念

双链表即所谓双向链表,所谓双向,指的是它的结点有2个指针——其中一个结点指向其直接前驱、另一个指向它的直接后继。

从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

2. 双链表结点的实现

使用来描述和实现双向链表的结点。那么,结点需要包含两块三个因素。第一块是其指针域,指针域中需要考虑两个方向的指针,一个是前驱指针、另一个是后继指针。对于一个在双向链表中的结点,每每两个之间的连接不是单向的,它一方面通过一个指针指向它的先驱结点,一方面通过一个指针指向它的后继结点,两个指针分别用属性prenext来表示。另一块是数据域,数据域中存储各种不确定形式的数据,我们预设其类型为any类型。

class Dnode{
    /**
     * 双向链表的结点,相比单向链表它有两个方向
     * @class Dnode
     * @constructor
     * @param pre {Lnode} 指前驱结点的指针
     * @param next {Lnode} 指向后继结点的指针
     */
    pre: Dnode | undefined | null;         // 指向先驱结点
    next: Dnode | undefined | null;        // 指向后继结点
    data:any;                              // 数据域
    constructor(data?:any){
        if(data){
            this.data = data;
            this.pre = null;
            this.next = null;
        }else{
            this.data = null;
            this.pre = null;
            this.next = null;
        }
    }
}

3. 头指针

实话说想实现一个链表,其实真的也未必需要一个头指针,比如我之前的单链表博文给出过头指针也没有的链表的TypeScript的实现。这里设计一个头指针,实际上就是链表结点的挂载点,它用来指向头节点。也就是说,我们认为头指针指向的第一个结点为首元结点。之前的博文已经说过,TypeScript没有C语言中那样的指针的概念,但是可以使用变量建立对对象的引用。我们使用一个类型为链表结点的属性headnext属性来假装头指针,这样我们就可以像对操作其它结点那样来操作首元结点,这也就是头指针的意义,否则,即没有头指针时,我们可能在某些方法中,又需要认为在链表外增加一个挂载点来挂载头节点进行操作。

4. 连接结点,实现双链表

和创建单链表不同的是创建双向链表的过程中每一个新节点都要和前驱节点之间建立两次链接即:

  • 将新节点的 pre 指针指向直接前驱节点;
  • 将直接前驱节点的 next 指针指向新节点;
export class LinkList{
    /**
     * 双链表类
     * @class LinkList
     * @constructor
     * @param head {Dnode} 头指针
     * @param length {number} 链表的长度
     */
    head: Dnode | null;                           // 头指针,只指向一个结点
    private length: number;                       // 链表所容纳结点的个数
    constructor();                                // 重载:若不传参数则构造一个空链表
    constructor(datas:any[]);                     // 重载:若给定一个数组则将数组中的元素依次放在链表中构造链表
    constructor(datas?){
        this.head = new Dnode();
        this.length = 0;                          // 初始化长度
        if(typeof datas == "object"){
            /**
             * 如果有给定了参数data
             */
            this.head.next = null;
            for(let i=0; i<datas.length; i++){
                this.append(datas[i])
            }
        }else{
            /**
             * 如果没有给定data参数,则构造一个空列表
             */
            this.head.next = null;
        }
    }
    is_empty():boolean{
        /**
         * 判断是否是空链表
         */
        if(this.head.next){return true}
        else{return false}
    }
    top(){
        /**
         * 查看链表头部结点(的数据)
         */
        if(this.head.next){
            return this.head.next.data
        }else{
            return null
        }
    }
    top_node(){
        /**
         * 查看链表头部结点
         */
         if(this.head.next){
            return this.head.next
        }else{
            return null
        }
    }
    clear():void{
        /**
         * 清空该双链表
         */
        this.head.next = null;  // 不能去清空头指针`head`,而要清空头指针的引用结点`head.next`
        this.length = 0;
    }
    append(data:any):void{
        /**
         * 在双链表右侧(尾)插入新的结点
         */
        let node = new Dnode(data);               // 用数据建立新的结点
        if(this.head.next==null){                 // 如果指向空即还没有一个结点
            this.head.next = node
        }else{
            let pointer = this.head;
            while(pointer.next){                  // 只要结点还存在
                pointer = pointer.next            // 向后一个结点引用
            }
            node.pre = pointer;
            pointer.next = node
        }
        this.length++;
    }
    append_left(data:any):void{
        /**
         * 在双链表左测(头)插入新的结点
         */
        let node:Dnode = new Dnode(data);
        if(this.head.next==null){
            this.head.next = node;
        }else{
            node.next = this.head.next;
            this.head.next.pre = node;
            this.head.next = this.head.next.pre;
        }
        this.length++;
    }
    insert(index:number, data: any):void{
        /**
         * 在指定索引处插入新的结点
         */
        let pointer:Dnode = this.head;
        let ct: number = 0;
        while(ct < index){
            pointer = pointer.next;
            ct++;
        }
        let node = new Dnode(data);
        node.next = pointer.next;
        node.pre = pointer;
        pointer.next = node;
    }
    to_node_array(){
        /**
         * 将链表转换为结点数组后返回
         * 数组的元素为结点
         */
        let ar: any[] = [];
        if(this.head.next){
            let pointer = this.head;               // 复制头指针的引用
            while(pointer.next){                   // 引用非空
                ar.push(pointer.next);             // 转载被引用结点的数据
                pointer = pointer.next             // 引用后移
            }
            return ar
        }else{
            return ar
        }
    }
    to_array():any[]{
        /**
         * 将链表转换为数组后返回
         * 数组的元素为结点的数据域
         */
        let ar: any[] = [];
        if(this.head.next){
            let pointer = this.head;               // 复制头指针的引用
            while(pointer.next){                   // 引用非空
                ar.push(pointer.next.data);        // 转载被引用结点的数据
                pointer = pointer.next             // 引用后移
            }
            return ar
        }else{
            return ar
        }
    }
}
目录
相关文章
|
9月前
|
JavaScript API C++
TypeScript 核心概念:`type` vs `interface`,如何明智选择?
TypeScript 核心概念:`type` vs `interface`,如何明智选择?
528 133
|
8月前
|
机器学习/深度学习 算法 数据可视化
近端策略优化算法PPO的核心概念和PyTorch实现详解
本文深入解析了近端策略优化(PPO)算法的核心原理,并基于PyTorch框架实现了完整的强化学习训练流程。通过Lunar Lander环境展示了算法的全过程,涵盖环境交互、优势函数计算、策略更新等关键模块。内容理论与实践结合,适合希望掌握PPO算法及其实现的读者。
1306 2
近端策略优化算法PPO的核心概念和PyTorch实现详解
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
500 30
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
726 25
|
12月前
|
存储 算法 物联网
解析局域网内控制电脑机制:基于 Go 语言链表算法的隐秘通信技术探究
数字化办公与物联网蓬勃发展的时代背景下,局域网内计算机控制已成为提升工作效率、达成设备协同管理的重要途径。无论是企业远程办公时的设备统一调度,还是智能家居系统中多设备间的联动控制,高效的数据传输与管理机制均构成实现局域网内计算机控制功能的核心要素。本文将深入探究 Go 语言中的链表数据结构,剖析其在局域网内计算机控制过程中,如何达成数据的有序存储与高效传输,并通过完整的 Go 语言代码示例展示其应用流程。
231 0
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
存储 缓存 算法
经典算法之链表篇(三)
经典算法之链表篇(三)
255 4
|
算法
经典算法之链表篇(二)
经典算法之链表篇(二)
271 4
|
算法 索引
经典算法之链表篇
经典算法之链表篇
300 4