数据结构(三)链表

一、链表的概念

链表和数组一样,可以用来存储一系列的元素,但是链表和数组的机制完全不同

数组:要存储多个元素,数组(或列表)可能是最常用的数据结构

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

2.在数组开头或中间插入数据的成本很高,需要大量元素的位移,比如说要在1345里面插入2,就需要把345往后都移动,即使是javascript里面的array类的底层原理也是如此,但数组通过下标值修改和获取数组性能比较高。

链表:也可以存储多个元素,且不需要连续的内存,链表的每个元素都由一个存储元素本身的节点和一个指向下一个元素的引用(指针或称为连接)组成

链表的优点:1.内存空间不是必须要连续的,可以充分利用计算机内存,实现灵活的内存动态管理。

2.链表不必在创建时就确定大小,并且大小可以无限的延伸下去。

3.链表在插入删除数组时,事件复杂度可以达到o(1).相对数组高校很多

但链表也有一些缺点:1.链表访问任何位置的元素都需要从头开始访问(无法跳过第一个元素访问任何一个元素)

2.无法直接通过下标来访问元素,需要从头一个个访问,知道找到对应的元素

二、链表的基本操作:

1.append(element):向列表尾部添加一个新的项

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

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

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

5.update(position,element):修改某个位置的元素

6.removeAt(position):从列表的特定位置移除一项。

7.remove(element):从列表中移除一项。

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

9.size():返回链表包含的元素个数。与数组的length属性类似。

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

1.append()方法实现

var  LinkedList=function(){
        var length=0;
          var head=null
           //辅助类:节点
            var Node=function (element){
                this.element=element
                this.next=null
            }
    
        this.append=function(element){
            var node=new Node(element)
            if(length==0){
               head=node
            }else{
                var current=head
                while(current.next){
                    current=current.next
                }
                current.next=node
            }
                length++
            }
            this.getHead=function(){
                return head
            }
        }
      

2.insert()方法实现

 this.insert = function (position, element) {
            // 判断位置
            var node = new Node(element)
            if (position > -1 && position < length) {
                if (position == 0) {
                    var current = head
                    head = node
                    head.next = current
                } else {
                    var index = 0;
                    var current = head;
                    var previous = null;
                    while (index < position) {
                        previous = current;
                        current = current.next
                        index++
                    }
                    previous.next = node
                    node.next = current
                    length++
                }
            }
            this.getHead = function () {
                return head
            }
        }
    }

3.get()方法实现

 this.get=function(position){
                var current=head
                var index=0
                if(position>-1&&position<=length){
                    current=current.next
                    index++
                }
                return current.element
            }

4. indexOf()方法实现

 this.indexOf=function(data){
                var current=head
                var index=0
                while(current){
                    if(current.element==data)
                    {
                        return index
                    }
                        current=current.next
                     index++
                }
                    return -1
                }               
        }

 var l=new LinkedList()
        l.append(1)
        l.append(2)
        l.append(3)
        console.log(l.indexOf(10))
        console.log(l.indexOf(1))

5. update()方法的实现

 this.update=function(position,data){
                var current=head
               var  index=0
               if(position>-1&&position<=length){
                   while(index<position){
                       current=current.next;
                       index++
                   }
                  current.element=data
                  return true
               } 
            }

6.removeAt()方法实现

this.removeAt=function(position){
                var index=0;
                var current=head;
                var previous=null;

                if(position>-1&&position<length){
                    if(position==0){
                       head=current.next
                    }
                    else{
                        while(index<position){
                            previous=current
                            current=current.next;
                            index++
                        }
                        previous.next=current.next
                    }
                   
                    length--
                }
            }
var l=new LinkedList()
        l.append(1)
        l.append(2)
        l.append(3)

7.remove()方法实现(用indexOf和removeAt实现)

 this.remove=function(element){
                return this.removeAt(this.indexOf(element))
            }

8. isEmpty()方法的实现

 this.isEmpty=function(){
                if(length!=0){
                    return true
                }
                return false
            } 

9.size()方法实现

  this.size = function () {
                return length
            }

10.toString()方法实现 

 this.toString = function () {
                var current = head
                var stringCurrent = ""
                while (current) {
                    stringCurrent += current.element + "";
                    current = current.next
                }
                return stringCurrent
            }

三、双向链表

1.单向列表:①只能从头遍历到尾或者从尾遍历到头(一般从头到尾)②也就是链表相连的过程是单向的③实现的原理是上一个链表中有一个指向下一个的引用.

缺点:一个节点既有向前连接的引用,也有一个向后连接的引我们可以轻松的到达下一个节点,但是回到前一个节点是很难的.还需要从头开始查找到当前元素的位置


2.双向链表:①既可以从头遍历到尾,又可以从尾遍历到头②也就是链表相连的过程是双向的.它的实现原理是一个节点既有向前连接的引用,也有一个向后连接的引用③双向链表可以有效的解决单向链表中提到的问题.

缺点:每次在插入或删除某个节点时,需要处理四个引用,而不是两个.也就是实现起来要困难一些

并且相当于单向链表,必然占用内存空间更大一些.

四、双向链表增加操作

1.forwardString():返回正向遍历的节点字符串形式

2.backString():返回反向遍历的节点字符串形式

toString、isEmpty、size、get、indexOf、update,remove方法实现和上述一样

append方法实现

 function DoublyLinkedList() {
            var length = 0;
            var tail = null;
            var head = null;

            var Node = function (data) {
                this.data = data;
                this.next = null;
                this.prev = null
            }
            this.append = function (data) {
                var node = new Node(data)
                if (length == 0) {
                    head = node
                    tail = node
                } else {
                    tail.next = node
                    node.prev = tail
                    //让最后的尾巴节点是node
                    tail = node
                }
                length++
            }
            this.getHead = function () {
                return head
            }
        }

backString和forwardString

 this.backString = function () {
                var current = head
                var DoublyString = ""
                while (current.next) {
                    DoublyString += current.data + ""
                    current = current.next
                }
                return DoublyString
            }
            this.forwardString = function () {
                var current = tail
                var DoublyString = ""
                while (current.prev) {
                    DoublyString += current.data + ""
                    current = current.prev
                }
                return DoublyString
            }

insert方法实现

  this.insert = function (position, data) {
                var index = 0
                var current = head
                var node = new Node(data)
                if (position < -1 || position >= length) return false
                if (length == 0) {
                    head = node
                    tail = node
                } else {
                    if (position == 0) {
                        head = node
                        node.next = current
                        current.prev = node
                    } else if (position == length-1) {
                        node.prev = tail
                        tail.next = node
                        tail = node
                    } else {
                        while (index < position) {
                            index++
                            current = current.next
                        }
                        node.next = current
                        node.prev = current.prev
                        current.prev.next = node
                        current.prev = node
                    }
                }
                length++
            }

 

 removeAt方法实现

 this.removeAt = function (position) {
                if (position < -1 || position >= length) return false
                if (length == 0) {
                    head = null
                    tail = null
                } else {
                    if (position == 0) {
                        head.next.prev = null
                        head = head.next

                    } else if (position == length - 1) {
                        tail.prev.next = null
                        tail = tail.prev
                    } else {
                        var index = 0
                        var current = head
                        while (index < position) {
                            current = current.next
                            index++
                        }
                        current.prev.next = current.next
                        current.next.prev = current.prev
                    }
                    length--
                }
            }
        }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值