zoukankan      html  css  js  c++  java
  • javascript实现数据结构与算法系列:功能完整的线性链表

    由于链表在空间的合理利用上和插入,删除时不需要移动等的有点,因此在很多场合下,它是线性表的首选存储结构。然而,它也存在着实现某些基本操作,如求线性表长度时不如顺序存储结构的缺点;另一方面,由于在链表中,结点之间的关系使用指针来表示,则数据元素在线性表中的“位序”的概念已淡化,而被数据元素在线性链表中的“位置”所代替。为此,从实际出发重新定义线性链表及其基本操作

    结构图:

      1 (function(module){
      2   function List() {
      3     this.head = null;
      4     this.tail = null;
      5   }
      6   module.exports = List;
      7 
      8   List.mergeList = function (a, b, compare) {
      9     var ha = a.head;
     10     var hb = b.head;
     11     var pa = ha;
     12     var pb = hb;
     13     var c = new List();
     14     var q;
     15     compare = compare || function (data1, data2) {
     16       return data1 <= data2;
     17     };
     18 
     19     while (pa && pb) {
     20       var data1 = pa.data;
     21       var data2 = pb.data;
     22 
     23       if (!compare(data1, data2)) {
     24         // delete head node
     25         q = a.delFirst();
     26         // append the node to c linkedList
     27         c.append(q);
     28         pa = a.head;
     29       } else {
     30         q = b.delFirst();
     31         c.append(q);
     32         pb = b.head;
     33       }
     34     }
     35 
     36     if (pa) {
     37       c.append(pa);
     38     } else {
     39       c.append(pb);
     40     }
     41 
     42     return c;
     43   };
     44 
     45   List.prototype = {
     46     makeNode: function(data, next){
     47       return {
     48         data: data != null ?  data : null,
     49         next: next || null
     50       };
     51     },
     52     delFirst: function () {
     53       var head = this.head;
     54       this.head = this.head.next;
     55       head.next = null;
     56 
     57       if(this.head === null) this.tail = null;
     58       return head;
     59     },
     60     append: function (node) {
     61       if (this.head !== null) {
     62         this.tail.next = node;
     63         this.tail = this.tail.next;
     64       } else {
     65         this.head = node;
     66         this.tail = node;
     67       }
     68     },
     69     add: function (data) {
     70       if (this.head === null) {
     71         this.head = this.makeNode(data);
     72         this.tail = this.head;
     73       } else {
     74         this.tail.next = this.makeNode(data);
     75         this.tail = this.tail.next;
     76       }
     77 
     78       this.tail.data = data;
     79     },
     80     'delete': function (data) {
     81       var current = this.head;
     82       var previous = this.head;
     83       var elem;
     84 
     85       while (current !== null) {
     86         if (data === current.data) {
     87           if (current === this.head) {
     88             this.head = current.next;
     89             elem =  current.data;
     90             break;
     91           }
     92 
     93           if (current === this.tail) this.tail = previous;
     94 
     95           previous.next = current.next;
     96           elem =  current.data;
     97           break;
     98         }
     99 
    100         previous = current;
    101         current = current.next;
    102       }
    103 
    104       if(this.head === null) this.tail = null;
    105 
    106       return elem ? elem : false;
    107     },
    108     insertAsFirst: function (data) {
    109       var temp = this.makeNode(data);
    110       temp.next = this.head;
    111       this.head = temp;
    112     },
    113     insertAfter: function (target, data) {
    114       var current = this.head;
    115       while (current !== null) {
    116         if (current.data === target) {
    117           var temp = this.makeNode(data);
    118           temp.next = current.next;
    119 
    120           if (current === this.tail) this.tail = temp;
    121 
    122           current.next = temp;
    123           return;
    124         }
    125 
    126         current = current.next;
    127       }
    128     },
    129     item: function (index) {
    130       var current = this.head;
    131 
    132       while (current !== null) {
    133         if (--index === 0) return current;
    134 
    135         current = current.next;
    136       }
    137 
    138       return null;
    139     },
    140     each: function (callback) {
    141       var current = this.head;
    142 
    143       while (current !== null) {
    144         callback(current);
    145         current = current.next;
    146       }
    147     },
    148     orderInsert: function(data, cmp){
    149       cmp = typeof cmp === 'function' ? cmp : function (a, b){
    150         if(a > b)
    151           return 1;
    152         else if(a === b)
    153           return 0;
    154         else
    155           return -1;
    156       };
    157       var previous = this.head;
    158       var current = this.head;
    159 
    160       if(current === null){
    161         this.head = this.tail = this.makeNode(data);
    162         return;
    163       }
    164 
    165       var me = this;
    166       while(current){
    167         var ret = cmp(data, current.data);
    168         // 如果插入元素大于当前元素,准备下次遍历
    169         if(ret > 0){
    170           previous = current;
    171           current = current.next;
    172 
    173           // 如果等于,直接插入到后面
    174         } else if(ret === 0){
    175           return insertBetween(data, previous, current);
    176 
    177           // 如果小于则插入到前节点和当前节点中
    178           // 因为已经是排序了,所以不需要多余判断了
    179         } else {
    180           if(this.head === previous && previous === current){
    181             return this.insertAsFirst(data);
    182           } else {
    183             return insertBetween(data, previous, current);
    184           }
    185         }
    186       }
    187 
    188       // 插入到最后一个结点
    189       previous.next = this.makeNode(data);
    190       this.tail = previous.next;
    191 
    192       function insertBetween(data, a, b){
    193         var temp = me.makeNode(data);
    194         temp.next = b;
    195         a.next = temp;
    196         return true;
    197       }
    198     }
    199   };
    200   /*
    201   var list = new List();
    202   list.add('b');
    203   list.insertAsFirst('a');
    204   list.insertAfter('b', 'c');
    205   console.log(list.item(2));
    206   console.log(JSON.stringify(list));
    207   list.each(function (node) {
    208     if (node.data === 'b') {
    209       console.log('get b in each');
    210     }
    211   });
    212   list['delete']('c');
    213   list['delete']('a');
    214   console.log(list);
    215 
    216   var list2 = new List();
    217   list2.add('c');
    218   list2.insertAsFirst('d');
    219   list2.insertAfter('d', 'b');
    220   console.log(JSON.stringify(list2));
    221 
    222   var list3 = List.mergeList(list, list2);
    223   console.log(list3);
    224   */
    225   /*
    226   var list = new List();
    227 
    228   list.orderInsert('e');
    229   list.orderInsert('b');
    230   list.orderInsert('c');
    231   list.orderInsert('a');
    232   list.orderInsert('d');
    233   list.orderInsert('f');
    234   */
    235 }(this.module || this));

    以下是对应的单元测试代码:

     1 describe('linkedList tests', function(){
     2 
     3   var list = new List();
     4 
     5   it('should find the second item', function(){
     6     list.add('b');
     7     expect(list.head.data).toBe('b');
     8     expect(list.tail.next).toBe(null);
     9 
    10     list.insertAsFirst('a');
    11     expect(list.head.data).toBe('a');
    12     expect(list.head.next.data).toBe('b');
    13 
    14     list.insertAfter('b', 'c');
    15     expect(list.item(2).data).toBe('b');
    16     expect(list.tail.data).toBe('c');
    17   });
    18 
    19   it('should remove one item', function(){
    20     expect(list['delete']('c')).toBe(true);
    21     list['delete']('a');
    22     expect(list.head.data).toBe('b');
    23   });
    24 
    25   var list2 = new List();
    26 
    27   it('should match the json', function(){
    28     list2.add('c');
    29     list2.insertAsFirst('d');
    30     list2.insertAfter('d', 'b');
    31     expect(JSON.stringify(list2)).toBe('{"head":{"data":"d","next":{"data":"b","next":{"data":"c","next":null}}},"tail":{"data":"c","next":null}}');
    32   });
    33 
    34   it('should merge the lists', function(){
    35     var list3 = List.mergeList(list, list2);
    36     expect(list3.head.data).toBe('d');
    37     expect(list3.head.next.data).toBe('b');
    38     expect(list3.head.next.next.data).toBe('c');
    39     expect(list3.tail.data).toBe('b');
    40   });
    41 });
  • 相关阅读:
    SQL SERVER2017 安装程序无法与下载服务器联系。无法安装机器学习服务的问题解决方式
    Kali Linux无法访问网络的问题
    Vue的冒泡事件
    记录阿里云ECS(Centos7.4)安装mysql 8.0.X服务
    沧桑巨变中焕发青春活力-记极1s HC5661A 打怪升级之路
    Asp.Net MVC过滤器小试牛刀
    C# Windows Service调用IBM Lotus Notes发送邮件
    记录一些js框架用途
    vc14(vs2015) 编译php7 记录
    C++ API方式连接mysql数据库实现增删改查
  • 原文地址:https://www.cnblogs.com/webFrontDev/p/3668187.html
Copyright © 2011-2022 走看看