数据结构——单向链表

一、链表概念
链表类似于火车:有一个火车头,火车头会连接一个节点,节点上有乘客(类似于数据),并且这个节点会连接下一个节点,依次类推)
在这里插入图片描述

二、数组与链表的区别
相同点:数组和链表都可以存储多个元素
不同点:

  • 数组的创建通常需要申请一段连续的内存空间(一整块的内存),并且大小是固定的(大多数编程语言数组都是固定的),所以当当前数组不能满足容量需求时,就需要扩容(一般情况下是申请一个更大的数组比如2倍,然后将原数组的元素复制过去)

  • 而且在数组开头或中间插入数据的成本很高,需要进行大量元素的位移

  • 链表中的元素在内存中不必是连续的空间

  • 链表的每个元素有一个存储元素本身的节点和一个指向下一个元素的引用(有些语言称为指针或者连接)组成
    相对于数组,链表的优点:
    1) 内存空间不必是连续的,可以充分利用计算机的内存,实现灵活的内存动态管理。
    2) 链表不必在创建时就确定大小,并且大小可以无限的延伸下去。
    3)链表在插入和删除时,相对数组效率高很多。
    相对于数组,链表的缺点:
    1)链表访问任何一个位置的元素时,都需要从头开始访问(无法跳过一个元素访问任何一个元素)。
    2)无法通过下标直接访问元素,需要从头一个个访问,直到找到对应的元素。
    三、单链表的封装
    首先,我们封装一个LinkedList类,来表示链表结构,并在LinkedList类中保存两个属性,一个是链表中的头结点,一个是链表的长度。然后在类里面再封装一个内部类Node,用于封装每一个节点上的信息,如下所示

//封装链表类
      function LinkedList(){
          //内部的类:节点类
          function Node(data){
              this.data=data
              this.next=null
          }
          //
          this.head = null
          this.length = 0
     }

四、单链表的主要操作

  • append(element:向列表尾部添加一个项

  • insert(position,element):向列表的特定位置插入一个项

  • get(position):获取对应位置的元素

  • indexOf(element):返回元素在列表中的索引,如果列表中没有该元素则返回-1

  • update(position,ele):修改某个位置的元素

  • removeAt(position):从列表的指定位置移除一项

  • remove(element):从列表中移除一项

  • isEmpty():如果链表中不包含任何元素,返回true,如果链表长度大于0返回false

  • size():返回链表包含的元素个数,与数组的length属性相关

  • toString():由于列表项用到了Node类,需要重写继承自JavaScript对象默认的toString方法,让其输出元素的值

下面我们将逐个实现
1、append(element:向列表尾部添加一个项
向链表尾部追加节点有两种情况:

  • 链表本身为空,新添加的数据是唯一的节点。
  • 链表不为空,需要向其他节点后面追加节点。
    如果添加的节点是第一个节点,我们只需要将头节点指向第一个节点。如果添加的节点是第二个节点,则必须找到第一个节点,并需要让第一个节点的next指向第二个节点,依次循环,直到找到尾节点。
 //封装链表类
        function LinkedList(){
            //内部的类:节点类
            function Node(data){
                this.data=data
                this.next=null
            }
            //属性
            this.head = null
            this.length = 0

            // 1.追加方法
            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.length+1
                this.length +=1
         }
            //2.tostring方法
            LinkedList.prototype.toString = function(){
                //1.定义变量
                var current = this.head
                var listString=''
                //2.循环获取一个个的节点
                while(current){
                    listString += current.data + " "
                    current = current.next
                }
                return listString
            }
        //3.insert方法
        LinkedList.prototype.insert = function(position,data){
                //1.对position进行越界判断
            if(position<0 || position > this.length) return false
                //2.根据data创建newNode
                var newNode = new Node(data)
                //3.判断插入的位置是否是第一个
                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
                }
                //4.length+1
                this.length +=1
                return true
        } 
        //4.get方法
        LinkedList.prototype.get = function(position){
            //1.越界判断
            if(position < 0 || position >= this.length) return null
            //2.获取对应的data
            var current = this.head
            var index = 0;
            while(index++ <position){
                current = current.next
            }
            return current.data
        }

        //5.indexOf()方法
        LinkedList.prototype.indexOf = function(data){
            //1.定义变量
            var current = this.head
            var index = 0
            //2.开始查找
            while(current){
                if(current.data == data){
                    return index
                }
                current = current.next
                index +=1
            }
            //3.找到最后没有找到则返回-1
            return -1
        }
        //6.update方法
        LinkedList.prototype.update = function(position,newData){
            //1.越界判断
            if(position < 0 || position >= this.length) return false
            //2.查找正确的节点
            var current = this.head
            var index = 0;
            while(index++ <position){
                current = current.next
            }
            //3.将position位置的node 的data修改成newData
            current.data = newData
            return true
        }

        //7.removeAt方法
        LinkedList.prototype.removeAt = function(position){
                //1.对position进行越界判断
            if(position<0 || position > this.length) return null
                //3.判断是否删除的是第一个节点
                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
                    }
                   //3.前一个节点的next指向,current的next指向
                    previous.next = current.next
                }
                //4.length+1
                this.length -=1
                return current.data
        } 
        //8.remove方法
        LinkedList.prototype.remove = function(data){
            //1.获取data在列表中的位置
            var position = this.indexOf(data)
            //2.根据位置信息,删除节点
            return this.remove(position)
        }
        //9.isEmpty方法
        LinkedList.prototype.isEmpty = function(){
            return this.length == 0
        }
        //10.size()方法
        LinkedList.prototype.size = function(){
            return this.length
    }
}

测试代码如下:

//测试代码
//1.创建LinkedList
var list = new LinkedList()
//2.测试append 方法
list.append('aaa')
list.append('bbb')
list.append('ccc')
alert(list)

在这里插入图片描述

//3.测试insert 方法
list.insert(0,'111')
list.insert(3,'222')
list.insert(5,'333')
alert(list)

在这里插入图片描述

//4.测试get方法
alert(list.get(0))
alert(list.get(3))
alert(list.get(5))

在这里插入图片描述
在这里插入图片描述

//5.测试indexOf方法
 alert(list.indexOf('aaa'))
 alert(list.indexOf('ccc'))

在这里插入图片描述
在这里插入图片描述

//6.测试update 方法
list.insert(0,'444')
list.insert(3,'555')
list.insert(5,'666')
alert(list)

在这里插入图片描述

//7.测试removeAt 方法
list.removeAt(0)
alert(list)
list.removeAt(3)
alert(list)

在这里插入图片描述
在这里插入图片描述

//9.测试isEmpty,size方法
alert(list.isEmpty())
alert(list.size())

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值