• javascript实现数据结构: 串的块链存储表示


    和线性表的链式存储结构相类似,也可采用链式方式存储串值。由于串结构的特殊性--结构中的每个数据元素是一个字符,则用链表存储串值时,存在一个“结点大小”的问题,即每个结点可以存放一个字符,也可以存放多个字符。

    下面是结点大小为4(即每个结点存放4个字符)的链表:

    head --> (a) --> (b) --> (c) --> ... --> (i)

    当结点大小大于1时,由于串长不一定是结点大小的整倍数,则链表中的最后一个结点不一定全被串值占满,此时通常补上“#”或其它非串值字符。

    为了便于进行串的操作,当以链表存储串值时,除头指针外还可附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度,称如此定义的串存储结构为块链结构。

    由于一般情况下,对串进行操作时,只需要从头向尾顺序扫描即可,则对串值不必建立双向链表。设尾指针的目的是为了便于进行连接操作,但应注意连接时需处理第一个串尾的无效字符。

    在链式存储方式中,结点大小的选择和顺序存储方式的格式选择一样都很重要,它直接影响到串处理的效率。如果串很长,这要求我们考虑串值的存储密度:

    存储密度 = 串值所占的存储位 / 实际分配的存储位

    串值的链式存储结构对某些串操作,如连接操作等有一定方便之处,但总的来说不如另外两种存储结构灵活,它占用存储量大且操作复杂。

    结构图:

    实现代码:

      1 function Chunk(chunkSize) {
      2         this.chunkSize = chunkSize || 4;
      3         this.ch = [];
      4         for (var i = 0; i < this.chunkSize; i++) {
      5             this.ch[i] = '#';
      6         }
      7         // type: Chunk
      8         this.next = null;
      9     }
     10 
     11     exports.LString = LString;
     12     function LString(chunkSize) {
     13         // type Chunk
     14         this.head = null;
     15         // type: chunk
     16         this.tail = null;
     17         // 串的当前长度
     18         this.length = 0;
     19         this.chunkSize = chunkSize || 4;
     20     }
     21 
     22     LString.prototype = {
     23         // 将字符串转换成LString类型
     24         strAssign: function (chars) {
     25             this.head = this.tail = new Chunk(this.chunkSize);
     26             this.length = chars.length;
     27 
     28             var current = this.head;
     29             for (var i = 0, len = chars.length; i < len; i++) {
     30                 current.ch[i % this.chunkSize] = chars[i];
     31                 if (i + 1 < len && (i + 1) % this.chunkSize === 0) {
     32                     current.next = new Chunk();
     33                     current = current.next;
     34                 }
     35             }
     36 
     37             this.tail = current;
     38         },
     39         // 字符串对比
     40         // TODO 是否去掉chunkSize的对比
     41         strCompare: function (tLString) {
     42             var current = this.head;
     43             var curT = tLString.head;
     44 
     45             if (this.length !== tLString.length) return false;
     46 
     47             while (current) {
     48                 for (var i = 0; i < this.chunkSize; i++) {
     49                     if (current.ch[i] !== curT.ch[i]) return false;
     50                 }
     51 
     52                 current = current.next;
     53                 curT = curT.next;
     54             }
     55 
     56             return true;
     57         },
     58         clearString: function () {
     59             this.head = this.tail = null;
     60             this.length = 0;
     61         },
     62         concat: function (tLSting) {
     63             if (!tLSting.length) return;
     64 
     65             var ret = new LString(this.chunkSize);
     66 
     67             if (this.head === null) {
     68                 copyString(ret, tLSting);
     69             } else {
     70                 ret.head = ret.tail = new Chunk(this.chunkSize);
     71                 copyString(ret, this);
     72 
     73                 var index = ret.tail.ch.indexOf('#');
     74                 if (index === -1) {
     75                     copyString(ret, tLSting);
     76                 } else {
     77                     copyString(ret, tLSting, ret.tail, tLSting.head, index);
     78                 }
     79             }
     80 
     81             return ret;
     82         },
     83         substring: function (pos, len) {
     84             pos = ~~pos || 0;
     85             len = ~~len || this.length;
     86             if (pos < 0 || pos > this.length - 1 || len < 0 || len > this.length - pos)
     87                 throw new Error('unexpected parameter');
     88 
     89             var sub = new LString(this.chunkSize);
     90             var current = findPosChunk(this, pos);
     91             var curS = sub.head = new Chunk(this.chunkSize);
     92             var i = 0;
     93             sub.length = len;
     94 
     95             outerloop: while (current) {
     96                 for (var j = 0, size = this.chunkSize; j < size; j++) {
     97                     if (i === len) {
     98                         break outerloop;
     99                     } else {
    100                         curS.ch[j] = current.ch[(i + pos) % this.chunkSize];
    101                         i++;
    102                         if ((i + pos) % this.chunkSize === 0) {
    103                             current = current.next;
    104                         }
    105                         if (i % this.chunkSize === 0 && (current.ch[i] || current.next)) {
    106                             curS.next = new Chunk(this.chunkSize);
    107                             curS = curS.next;
    108                         }
    109                     }
    110                 }
    111             }
    112 
    113             return sub;
    114         },
    115         toString: function () {
    116             var current = this.head;
    117 
    118             if (current === null) return '';
    119 
    120             var str = '';
    121             while (current) {
    122                 for (var i = 0, len = this.chunkSize; i < len; i++) {
    123                     var ch = current.ch[i];
    124                     if (ch === '#') {
    125                         return str;
    126                     } else {
    127                         str += current.ch[i];
    128                     }
    129                 }
    130                 current = current.next;
    131             }
    132 
    133             return str;
    134         }
    135     };
    136 
    137     function findPosChunk(lString, pos) {
    138         var current = lString.head;
    139         while (current) {
    140             for (var i = 0, len = lString.chunkSize; i < len; i++) {
    141                 if (pos-- === 0) return current;
    142             }
    143             current = current.next;
    144         }
    145     }
    146 
    147     function copyString(destination, target, curD, currT, offset) {
    148         offset = offset || 0;
    149         currT = currT || target.head;
    150         curD = curD || destination.head;
    151         var k = 0;
    152 
    153         while (currT) {
    154             for (var i = 0, len = target.chunkSize; i < len; i++, k++) {
    155                 var j = k % curD.chunkSize + offset;
    156                 curD.ch[j % curD.chunkSize] = currT.ch[i];
    157 
    158                 if ((j + 1) % curD.chunkSize === 0 && (currT.ch[i + 1] || currT.next)) {
    159                     curD.next = new Chunk(destination.chunkSize);
    160                     curD = curD.next;
    161                 }
    162             }
    163 
    164             currT = currT.next;
    165         }
    166 
    167         destination.tail = curD;
    168         destination.length += target.length;
    169     }
    170 
    171     var a = new LString();
    172     var b = new LString();
    173     var c = new LString();
    174 
    175     a.strAssign('abcdefg');
    176     console.log(a + '');
    177     b.strAssign('hijklmno');
    178     console.log(b + '');
    179     c.strAssign('abcdefg');
    180     console.log(a.strCompare(b));
    181     console.log(a.strCompare(c));
    182     var t = a.concat(b);
    183     console.log(t + '');
    184     t = t.substring(2, 5);
    185     console.log(t + '');

    单元测试代码:

     1 describe('LString tests', function(){
     2     var a = new LString(5);
     3     var b = new LString(4);
     4     var c = new LString(5);
     5     var t;
     6 
     7     it('should assign string', function(){
     8         a.strAssign('abcdefg');
     9         expect(a + '').toBe('abcdefg');
    10 
    11         b.strAssign('hijklmno');
    12         expect(b + '').toBe('hijklmno');
    13 
    14         c.strAssign('abcdefg');
    15         expect(c + '').toBe('abcdefg');
    16     });
    17 
    18     it('should compare', function(){
    19         expect(a.strCompare(b)).toBe(false);
    20         expect(a.strCompare(c)).toBe(true);
    21     });
    22 
    23     it('should concat', function(){
    24         t = a.concat(b);
    25         expect(t + '').toBe('abcdefghijklmno');
    26     });
    27 
    28     it('should substring', function(){
    29         t = t.substring(2, 5);
    30         expect(t + '').toBe('cdefg');
    31     });
    32 });
    View Code
  • 相关阅读:
    今天没有写的,唱首歌吧。。
    UILocalNotification实现本地的闹钟提醒的方法。
    又是动画效果~
    c位运算符
    javascript如何调用objectivec的方法
    在tableview索引中显示搜索符号的方法
    检查数据库|| 复制数据库文件
    往sqlite中写入图片二进制数据及读取源码 for iphone
    [Cocoa]深入浅出 Cocoa 之消息(罗朝辉)
    关于malloc问题的改错笔试常考
  • 原文地址:https://www.cnblogs.com/webFrontDev/p/3695163.html
Copyright © 2020-2023  润新知