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 + '');

原文地址:https://www.cnblogs.com/asds/p/7651457.html