【JS数据结构与算法】单向链表的封装及其方法

目录

一、什么是链表?

二、链表的封装

三、追溯方法append(element)

四、toString()

五、inset(position, element)

六、get(position)

七、indexOf(element)

八、upDate(position, element)

九、removeAt(position)

十、remove(element)

十一、判断链表是否为空

十二、返回链表的长度


一、什么是链表?

        链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

二、链表的封装

function linkedList(){
      
      // 封装一个内部类
      function Node(data){
        this.data = data;
        this.next = null;
      }


      // 属性,声明一个链表头和链表的长度
      this.head = null;
      this.length = 0;
}

三、追溯方法append(element)

向链表尾部添加一个新的项。

linkedList.prototype.append = function(data){

        // 1、创建新节点
        var newNode = new Node(data);

        // 2、判断链表是否为空
        if(this.length == 0){ //2.1 链表为空
          this.head = newNode;
        }else{                 //2.2 链表不为空
          // 找到最后一个节点
          var current = this.head;
          while(current.next){
            current = current.next;
          }

          // 最后的节点的Next指向新的节点
          current.next = newNode;
        }

        // 3、长度要加1
        this.length += 1;
}

四、toString()

由于链表项使用了Node类,就需要重写继承自JavaScript对象默认的toString方法,让其只输出元素的值。

linkedList.prototype.toString = function(){
        // 1、先定义变量
        var current = this.head;
        var listString = '';

        // 将每次遍历的结果组成字符串
        while(current){
          listString += current.data + ' ';

          // 加完一个元素后,指向下一个元素
          current = current.next;
        }

        // 返回字符串
        return listString;
}

append方法与toString方法测试

      // 测试代码
      // 创建linkedList
      var list = new linkedList();

      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');
      
      alert(list); // a b c d

五、inset(position, element)

向队列的特定位置插入一个新的元素。

这种方法与append不同的是,在任何一个有效的地方插入一个元素,首先需要给定的参数是位置(position)和值(data)

1、利用原型,给整个类添加一个方法

// 三、inset方法
linkedList.prototype.inset = function(position, data){

}

2、需要先限制position的有效范围

假设链表中有四个元素,那么position的值就不能为负数,且不可以超过链表的长度。

if (position < 0 || position > this.length) return false;

 

3、根据data创建linkedList

var newNode = new Node(data);

4、判断所插入的节点位置是否在0的位置。

    4.1如果是,先让新节点的next指向head,再将head指向新节点。注意:这里的顺序不可颠倒。

if(position == 0){  //当所插入的节点位置在0的位置时
    // 先让新节点的next指向head
    newNode.next = this.head;
    // 再将head指向新节点
    this.head = newNode;
}

   

    4.2如果不是,则需寻找到相应位置插入。

这里先定义三个变量,分别是index、current和previous

index变量:等于0,从第一个节点的位置开始

current变量:指向head;

previous变量:指向空,表示第一个节点之前没有节点。

var index = 0;   //指向第一个节点的位置
var current = this.head;   //将current变量指向head
var previous = null;    //将变量previous指向空,表示第一个节点之前没有节点

在找到相应位置之前,每一次操作都保存两个位置。

 
while(index++ < position){ //相比较后++
    previous = current; //只要满足条件,就将current的赋予previous,表示保存需要插入节点位置的上一个位置
    current = current.next;  //然后current指向下一个节点继续查找
}

5、插入节点

//插入节点
newNode.next = current;  //先让新节点的next指向查找到的位置上的节点
previous.next = newNode; //再将保存的上一个节点的next指向新节点

6、链表长度加1

// 6、length+1
this.length += 1;

 

7、完整代码

linkedList.prototype.inset = function(position, data){
        if (position < 0 || position > this.length) return false;
        var newNode = new Node(data);
        if(position == 0){
          newNode.next = this.head;
          this.head = newNode;
        }else {
            var index = 0;
            var current = this.head;
            var previous = null;
            while(index++ < position){
              previous = current;
              current = current.next;
            }
            newNode.next = current;
            previous.next = newNode;
        }
        this.length += 1;
        return true;
}

8、测试代码

      // 测试代码
      // 创建linkedList
      var list = new linkedList();

      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');
      
      alert(list); // a b c d

      list.inset(2,'e');

      alert(list); // a b e c d

六、get(position)

获取对应位置的元素。

以变量index去寻找到对应的位置并返回data

linkedList.prototype.get = function(position){
        // 越界判断
        if (position < 0 || position >= this.length) return false;

        var index = 0;
        var current = this.head;
        while(index++ < position){
          current = current.next;
        }
        return current.data;
}

测试代码

      // 测试代码
      // 创建linkedList
      var list = new linkedList();

      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');


      alert(list.get(2)); // c
      alert(list.get(3)); // d
      alert(list.get(4)); //false
      alert(list.get(-4)); //false

七、indexOf(element)

返回元素在链表中的索引。

linkedList.prototype.indexOf = function(data){
        //定义变量
        var index = 0;
        var current = this.head;
        //当current不指向空时判断数据是否相同
        while(current){
          if (current.data == data) return index;
          current = current.next;
          index += 1; 
        }
        return false;
}

代码测试

      // 测试代码
      // 创建linkedList
      var list = new linkedList();

      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');

      alert(list.indexOf('a')); //0
      alert(list.indexOf('b')); //1
      alert(list.indexOf('c')); //2
      alert(list.indexOf('d')); //3
      alert(list.indexOf('tt')); //false

八、upDate(position, element)

修改某个位置的元素。

upDate方法其实跟get方法类似,只是将其数据更改。

linkedList.prototype.upDate = function(position, data){

        // 越界判断
        if (position < 0 || position >= this.length) return false;

        var index = 0;
        var current = this.head;
        while(index++ < position){
          current = current.next;
        }
        current.data = data;
        return true;
}

测试代码

      // 测试代码
      // 创建linkedList
      var list = new linkedList();

      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');

      alert(list); //a b c d

      list.upDate(1,'e')
      alert(list); //a e c d

九、removeAt(position)

从链表中移除特定位置的一项。

removeAt删除一个节点方法与inset方法相似,只是操作不同。

1、利用原型,给整个类添加一个方法

linkedList.prototype.removeAt = function(position){

}

2、限制position的有效范围

if (position < 0 || position > this.length) return false; //position小于0或者大于链表长度时删除失败

3、判断所删除的节点位置是否在0的位置。

   3.1 如果是,head直接指向第一个节点的next

if(position == 0){  //3.1当所删除的节点位置在0的位置时
          this.head = this.head.next;
}

   

    3.2如果不是,则需寻找到相应位置删除。

这里先定义三个变量,分别是index、current和previous

index变量:等于0,从第一个节点的位置开始

current变量:指向head;

previous变量:指向空,表示第一个节点之前没有节点。

var index = 0;   //指向第一个节点的位置
var current = this.head;   //将current变量指向head
var previous = null;    //将变量previous指向空,表示第一个节点之前没有节点

在找到相应位置之前,每一次操作都保存两个位置。

 
while(index++ < position){
    previous = current;
    current = current.next;
}

4、删除节点

// 4、删除节点
// 前一个节点的next指向,current的next指向
previous.next = current.next;

5、链表长度减去1

// 5、length-1
this.length -= 1;

6、完整代码

linkedList.prototype.removeAt = function(position){
        if (position < 0 || position > this.length) return null;
        var current = this.head;
        if(position == 0){
          this.head = this.head.next;
        }else {
            var index = 0;
            var previous = null;
            while(index++ < position){
              previous = current;
              current = current.next;
            }
            previous.next = current.next;
          }
          this.length -= 1;
          return current.data;
}

7、代码检验

      // 测试代码
      // 创建linkedList
      var list = new linkedList();

      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');

      alert(list); //a b c d


      alert('删除的节点为:' + list.removeAt(1) + ',最终链表为:' + list); //删除的节点为:b,最终链表为:a c d 

十、remove(element)

从链表中删除一项。

先确定该元素的位置,然后再利用位置进行删除,其实就是直接调用indexOf()与removeAt()两个方法。

linkedList.prototype.remove = function(data) {
    // 1、获取data在链表中的位置
    var position = this.indexOf(data);
    
    // 2、根据位置,删除节点
    return this.removeAt(position);
}

测试代码

      // 测试代码
      // 创建linkedList
      var list = new linkedList();

      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');

      alert(list); //a b c d


      alert('删除的节点为:' + list.remove('a') + ',最终链表为:' + list); //删除的节点为:a,最终链表为:b c d 

十一、判断链表是否为空

linkedList.prototype.isEmpty = function(){
    return this.length === 0;
}

十二、返回链表的长度

linkedList.prototype.size = function(){
    return this.length;
}

十一、十二代码测试

      // 测试代码
      // 创建linkedList
      var list = new linkedList();


      list.append('a');
      list.append('b');
      list.append('c');
      list.append('d');

      alert(list); //a b c d
      
      alert(list.size()); //4

      alert(list.isEmpty()); //false

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值