前端必备算法--链表

链表

链表是一种物理存储单元上非连续、非顺序的存储结构。链表由一系列结点组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
在这里插入图片描述

链表的基本特征

  1. 每个元素除了存储数据,需要有额外的内存存储一个引用(地址),来指向下一个元素;
  2. 每个元素占用的内存空间并不要求是连续的;
  3. 往往使用链表的第一个节点(根节点)来代表整个链表;
  4. 长度是可变的,随时可以增加和删除元素;
  5. 插入和删除元素的效率极高;
  6. 由于要存储下一个元素的地址,会增加额外的内存开销;
  7. 通过下标查询链表中的某个节点,效率很低,因此链表的下标遍历效率低。

手动实现链表功能

构造链表

/**
 * 构造函数  表示链表的一个节点
 * 
 */
  function Node(value){
    this.value = value;  //节点的数据
    this.next = null;  //下一个节点的地址
  }

遍历链表打印节点

/* 遍历一个链表打印每个节点的数据
    *@param root 链表的根节点
  */
  function print(root){
    /*
    第一种:
    // var node = root;
    while(node){
      //如果node有值。打印
      console.log(node.value);
      node = node.next;
    }
    */
   //分治法
  //  var node = root;
    if(root){
      console.log(root.value); //打印自己
      print(root.next); 
    }
  }

计算链表的长度

/***
   *计算链表的长度 
   */
    function count(root){
      /** 
      var count = 0;
      var node = root;
      while(node){
        count ++;
        node = node.next;
      }
      return count;*/
      if(!root)  return 0;  //链表没有节点
      return 1 + count(root.next); //1表示根节点占用一个数量
    }

通过下标获取链表中的某个数据

/**
     * 得到链表某个下标的数据
     * @param{*} root
     * @param{*} index
     */
    function getValue(root,index){
    /**
     * 判断某个节点是否是我要查找的节点
     * @param {*} node  表示某个节点
     * @param {*} i  该节点是第几个节点
     */
      function _getValue(node,i){
        if(!node)  return null;
        if(i == index)  return node;
        return _getValue(node.next,i+1);
      }
      return _getValue(root,0);
    }

通过下标设置链表中的某个数据

 /**
     * 设置链表某个位置的数据
     * @param {*} root 
     * @param {*} index 
     * @param {*} value 
     */
    function setValue(root,index,value){
        function _setValue(node,i){
          if(!node) return ;
          if(i == index){
            node.value = value;
          }else{
              _setValue(node.next,i+1);
          }
        }
        _setValue(root,0);
    }

在链表某一个节点之后加入一个新节点

/**
 * 在链表的某个节点之后加入一个新的节点
 * @param {*} node 
 * @param {*} index 
 * @param {*} newValue 
 */
function insertAfter(node,newValue){
  var newNode = new Node(newValue);
  newNode.next = node.next;
  node.next = newNode; 
}

在链表末尾加入一个新节点

/**
 * 在链表的末尾加入一个新的节点
 * @param {*} node 
 * @param {*} newValue 
 */
function push(root,newValue){
  if(!root.next){
    var newNode = new Node(newValue);
    root.next = newNode;
  }else{
    push(root.next,newValue);
  }
}

删除一个节点

方法1:

/**
 * 通过下标删除某一个节点
 * @param {*} root 
 * @param {*} index 
 */
function removeNode(root,index){
  function _remove(root,i){
    if(!root || root.next == null) return null;
    if(i == index-1){
      root.next = root.next.next;
    }else{
      _remove(root.next,i+1);
    }
  }
  return _remove(root,0);
}

方法2:

/**
 * 通过值删除一个节点
 * @param {*} root 
 * @param {*} nodeValue 
 */
function  removeNode(root,nodeValue){
  if(!root || root.next == null) return;
  if(root.next.value == nodeValue){
      root.next = root.next.next;

  }else{
    removeNode(root.next,nodeValue);
  }
}

链表倒序

/**链表倒叙
 * 给定一个链表,返回一个倒序后的链表
 * @param {*} root 
 */
 function reverse(root){
    if(root.next == null) return;
    if(root.next.next == null){
      var temp = root.next;
      root.next.next = root;
      root.next = null;
      return temp;
    }else{
      var temp = reverse(root.next);
      root.next.next = root;
      root.next = null;
      return temp;
    }
  }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值