JS--学习链表以及单链表合并、翻转、两两交换节点位置、单向链表和单向循环链表实现约瑟夫环问题等

JS–学习链表

一、链表结构

1、单向链表

单向链表

2、双向链表

双向链表

3、单向循环链表

单向循环链表

4、双向循环链表

双向循环链表
5、链表与数组

数组:js中数组中可以存储不同数据类型的数据,查找元素很方便(随机访问),可以根据下标快速查找;但是删除、添加都比较复杂,会是数组中元素移动。

链表:查找数据不如数组方便,但是删除、插入等操作时会比较迅速,因为链表不需要移动多个元素,使用指针直接将元素添加进来或删除掉,但是空间会有部分浪费(使用部分空间存储指针,以空间换时间)

二、封装链表

1、单向链表

class NodeOne {
   //每一个节点
    constructor(element) {
   
        this.data = element;//数据
        this.next = null;//指针
    }
}
//下标由0开始
class OneLinkList {
   //单向链表
    constructor() {
   
        this.head = null;//头指针
        this.length = 0;//链表长度
    }
    //添加节点
    append(element) {
   
        //创建一个新节点
        let node = new NodeOne(element);
        //this.head == null和this.length == 0都可以判断链表为空
        if (this.head == null || this.length == 0) {
   
            //链表为空时直接添加节点
            this.head = node;
        } else {
   
            //链表部位空时找到尾部节点,在尾部节点后面添加节点
            let current = this.head;
            //找到next == null,不再往后找
            while (current.next != null) {
   //判断条件可以换为current.next
                //next为空就继续往下找
                current = current.next;
            }
            //next为空后就将next指向刚创建的新节点
            current.next = node;
        }
        this.length++;//每添加一个节点就将链表长度+1
    }
    //在任意位置和它前一个之间插入节点
    insert(element, position) {
   
        if (position < 0 || position > this.length || !Number.isInteger(position)) {
   
            return -1;
        }
        let node = new NodeOne(element);
        let current = this.head;
        if (position == 0) {
   
            if (this.head == null || this.length == 0) {
   
                this.head = node;
            } else {
   
                //链表不为空时插入到头部
                current.next = this.head;//先将新的节点连接到头指针指向的节点
                this.head = node;//再将头指针指向新的节点
            }
        } else if (position == this.length) {
   
            this.append(node);
        } else {
   
            //方法一:
            let current = this.head, index = 0;
            while (index++ < position - 1) {
   
                current = current.next;
            }
            node.next = current.next;
            current.next = node;
            //方法二:
            // let current = this.head;
            // let previous = null;
            // let index = 0;
            // while (index < position) {
   
            //     previous = current;
            //     current = current.next;
            //     index++;
            // }
            // node.next = current;
            // previous.next = node;
        }
        this.length++;
    }
    //便于查看链表内容
    toString() {
   
        let listData = '';
        let current = this.head;
        while (current) {
   
            listData += '-' + current.data;
            current = current.next;
        }
        return listData.slice(1);
    }
    //根据数据查找节点
    indexOf(element) {
   
        let current = this.head;
        let index = 0;
        while (current) {
   
            if (current.data === element) {
   
                return index;
            }
            index++;
            current = current.next;
        }
        return -1;
    }
    //移除特定位置的节点
    removeAt(position) {
   
        //不合法的位置返回-1
        if (position < 0 || position > this.length || !Number.isInteger(position)) {
   
            return -1;
        }
        //删除第一个
        if (position == 0) {
   
            //只有一个节点
            if (this.length == 1) {
   
                this.head = null;
            } else {
   
                //有多个节点
                this.head = this.head.next;
            }
            // //删除最后一个
            }else if(position == this.length - 1){
   
                let current = this.head;
                let index = 0;
                while(index++ < position - 1){
   
                    current = current.next;
                }
                current.next = null;
        //移除中间部分和尾部合并    
        } else {
   
            let current = this.head;
            let index = 0;
            while (index++ < position) {
   
                current = current.next;
            }
            current.next = current.next.next;
        }
        this.length--;
    }
    isEmpty(){
   
        return this.length == 0;
    }
    size(){
   
        return this.length;
    }
    remove(element){
   
        return this.removeAt(this.indexOf(element));
    }

}

2、双向链表

class DoubleNode {
   
    constructor(element) {
   
        this.data = element;
        this.next = null;//下一个
        this.previous = null;//前一个
    }
}
class DoubleLinkList {
   
    constructor() {
   
        this.head = null;//头指针
        this.length = 0;
        this.tail = null;//尾指针
    }
    //添加节点
    append(element) {
   
        let node = new DoubleNode(element);
        if (this.head == null) {
   //链表为空时
            this.head = node;
            this.tail = node;
        } else {
   //不为空时
            //前两句可以交换位置
            this.tail.next = node;
            node.previous = this.tail;
            this.tail = node;
        }
        this.length++;
    }
    //正向遍历
    toAfterString() {
   
        let re = '';
        let current
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值