高级前端之js数据结构之线性结构

17 篇文章 0 订阅
16 篇文章 0 订阅

上一节课 我们讲到了基本的堆和队列,不明白的同学可回过头再学习一下,这一节课,我们花时间重点讲一下线性结构
在讲数组之前,我们先回顾下开发者常用的数组
数组其实是一种线性表的顺序存储结构,它的特点是用一组地址连续的存储单元依次存储数据元素。而它的缺点也正是其特点而造成,比如对数组做删除或者插入的时候,可能需要移动大量的元素。

这里大致模拟一下数组的插入操作:

function insert(arr, index, data) {
  for (let i = arr.length; i >index; i--) {
    arr[i] = arr[i - 1];
  }
  arr[index] = data;
}

从上面的代码可以看出数组的插入以及删除都有可能会是一个O(n)的操作。从而就引出了链表这种数据结构,链表不要求逻辑上相邻的元素在物理位置上也相邻,因此它没有顺序存储结构所具有的缺点,当然它也失去了数组在一块连续空间内随机存取的优点。

链表又分单项链表 双向链表及循环链表 这节课我们从基本的入手,先讲单项链表
单向链表的特点:

  • 用一组任意的内存空间去存储数据元素(这里的内存空间可以是连续的,也可以是不连续的)
  • 每个节点(node)都由数据本身和一个指向后续节点的指针组成
  • 整个链表的存取必须从头指针开始,头指针指向第一个节点
  • 最后一个节点的指针指向空(NULL)

链表中的几个主要操作

  1. 创建节点
  2. 插入节点
  3. 搜索/遍历节点
  4. 删除节点
  5. 合并

初始化节点

  • 指针指向空
  • 存储数据
class Node {
        constructor(key) {
            this.key = key;
            this.next = null;
        }
    }
**

初始化链表

  • 头节点为空

  • 链表长度为0

class List {
    constructor() {
        this.head = null;
        this.length = 0;
    }

插入节点(在尾部插入节点)

  • 插入操作只需要去调整节点的指针即可,两种情况:
  • head没有指向任何节点,说明当前插入的节点是第一个
    • head指向新节点
    • 新节点的指针指向NULL
  • head有指向的节点
    • head指向新的节点

    • 新节点的指针指向原本head所指向的节点

      // 往尾部插入数据

append(ele) {
    const node = new Node(ele);
    if (this.head) {
        let current = this.head;
        while (current.next) {
            current = current.next
        }
        current.next = node;

    } else {
        this.head = node;
    }
    this.length++;
}
      

任意位置插入元素

 insert(index, ele) {
        if (index > -1 && index < this.length) {
            const node = new Node(ele);
            let current = this.head;
            let previous = null;
            let idx = 1;
            if (this.head != 0) {
                while (idx < index) {
                    previous = current;
                    current = current.next;
                    idx++;
                }
                node.next = current;
                previous.next = node;
                this.length++;
            } else {
                this.head = node;
            }
        } else {
            console.error(`请输入0到${this.length}的值`);
            return false
        }
    }
        // 移除指定位置元素
        removeAt(index) {
            if (index > -1 && index < this.length) {
                let previous = null;
                let current = this.head;
                let idx = 0;
                if (index == 0) {
                    this.head = current.next;
                } else {
                    while (idx < index) {
                        previous = current;
                        current = current.next;
                        idx++;
                    }
                    previous.next = current.next;
                }
                this.length--;
                return current.key;

            } else {
                console.error(`请输入0到${this.length}的值`);
                return false
            }
        }

搜索节点

  • 从head开始查找
  • 找到节点中的key等于想要查找的key的时候,返回该节点

// 寻找元素下标

findIndex(ele) {
    let current = this.head;
    let index = 0;
    while (index < this.length) {
        if (current.key == ele) {
            return index + 1;
        } else {
            current = current.next;
            index++;
        }
    }
    return -1
}
    isEmpty() {
        return !this.length;
    }
    // 转为字符串
    toString() {
        let str = "";
        let current = this.head;
        while (current) {
            str = str + current.key;
            current = current.next;
        }
        return str;
    }
}

完整的代码块如下

class Node {
        constructor(key) {
            this.key = key;
            this.next = null;
        }
    }
    class List {
        constructor() {
            this.head = null;
            this.length = 0;
        }

        // 往尾部插入数据
        append(ele) {
            const node = new Node(ele);
            if (this.head) {
                let current = this.head;
                while (current.next) {
                    current = current.next
                }
                current.next = node;

            } else {
                this.head = node;
            }
            this.length++;
        }
        // 任意位置插入元素
        insert(index, ele) {
            if (index > -1 && index < this.length) {
                const node = new Node(ele);
                let current = this.head;
                let previous = null;
                let idx = 1;
                if (this.head != 0) {
                    while (idx < index) {
                        previous = current;
                        current = current.next;
                        idx++;
                    }
                    node.next = current;
                    previous.next = node;
                    this.length++;
                } else {
                    this.head = node;
                }
            } else {
                console.error(`请输入0到${this.length}的值`);
                return false
            }
        }
        // 移除指定位置元素
        removeAt(index) {
            if (index > -1 && index < this.length) {
                let previous = null;
                let current = this.head;
                let idx = 0;
                if (index == 0) {
                    this.head = current.next;
                } else {
                    while (idx < index) {
                        previous = current;
                        current = current.next;
                        idx++;
                    }
                    previous.next = current.next;
                }
                this.length--;
                return current.key;

            } else {
                console.error(`请输入0到${this.length}的值`);
                return false
            }
        }
        // 寻找元素下标
        findIndex(ele) {
            let current = this.head;
            let index = 0;
            while (index < this.length) {
                if (current.key == ele) {
                    return index + 1;
                } else {
                    current = current.next;
                    index++;
                }
            }
            return -1
        }
        isEmpty() {
            return !this.length;
        }
        // 转为字符串
        toString() {
            let str = "";
            let current = this.head;
            while (current) {
                str = str + current.key;
                current = current.next;
            }
            return str;
        }
    }
    const list = new List();

    console.log(list);
    list.append(2);
    list.append(6);
    list.append(24);
    list.append(152);

    list.insert(3, 18);
    console.log(list);
    console.log(list.findIndex(24));
    console.log(list.removeAt(1));
    console.log(list)


这节课我们就讲到这里,不好之处,欢迎大家留言。 
*[上一篇:高级前端之js数据结构与算法](https://blog.csdn.net/weixin_43097944/article/details/115027768)*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值