javascript实现数据结构与算法系列:功能完整的线性链表
2014-04-16 11:19
555 查看
由于链表在空间的合理利用上和插入,删除时不需要移动等的有点,因此在很多场合下,它是线性表的首选存储结构。然而,它也存在着实现某些基本操作,如求线性表长度时不如顺序存储结构的缺点;另一方面,由于在链表中,结点之间的关系使用指针来表示,则数据元素在线性表中的“位序”的概念已淡化,而被数据元素在线性链表中的“位置”所代替。为此,从实际出发重新定义线性链表及其基本操作
结构图:
以下是对应的单元测试代码:
结构图:
(function(module){ function List() { this.head = null; this.tail = null; } module.exports = List; List.mergeList = function (a, b, compare) { var ha = a.head; var hb = b.head; var pa = ha; var pb = hb; var c = new List(); var q; compare = compare || function (data1, data2) { return data1 <= data2; }; while (pa && pb) { var data1 = pa.data; var data2 = pb.data; if (!compare(data1, data2)) { // delete head node q = a.delFirst(); // append the node to c linkedList c.append(q); pa = a.head; } else { q = b.delFirst(); c.append(q); pb = b.head; } } if (pa) { c.append(pa); } else { c.append(pb); } return c; }; List.prototype = { makeNode: function(data, next){ return { data: data != null ? data : null, next: next || null }; }, delFirst: function () { var head = this.head; this.head = this.head.next; head.next = null; if(this.head === null) this.tail = null; return head; }, append: function (node) { if (this.head !== null) { this.tail.next = node; this.tail = this.tail.next; } else { this.head = node; this.tail = node; } }, add: function (data) { if (this.head === null) { this.head = this.makeNode(data); this.tail = this.head; } else { this.tail.next = this.makeNode(data); this.tail = this.tail.next; } this.tail.data = data; }, 'delete': function (data) { var current = this.head; var previous = this.head; var elem; while (current !== null) { if (data === current.data) { if (current === this.head) { this.head = current.next; elem = current.data; break; } if (current === this.tail) this.tail = previous; previous.next = current.next; elem = current.data; break; } previous = current; current = current.next; } if(this.head === null) this.tail = null; return elem ? elem : false; }, insertAsFirst: function (data) { var temp = this.makeNode(data); temp.next = this.head; this.head = temp; }, insertAfter: function (target, data) { var current = this.head; while (current !== null) { if (current.data === target) { var temp = this.makeNode(data); temp.next = current.next; if (current === this.tail) this.tail = temp; current.next = temp; return; } current = current.next; } }, item: function (index) { var current = this.head; while (current !== null) { if (--index === 0) return current; current = current.next; } return null; }, each: function (callback) { var current = this.head; while (current !== null) { callback(current); current = current.next; } }, orderInsert: function(data, cmp){ cmp = typeof cmp === 'function' ? cmp : function (a, b){ if(a > b) return 1; else if(a === b) return 0; else return -1; }; var previous = this.head; var current = this.head; if(current === null){ this.head = this.tail = this.makeNode(data); return; } var me = this; while(current){ var ret = cmp(data, current.data); // 如果插入元素大于当前元素,准备下次遍历 if(ret > 0){ previous = current; current = current.next; // 如果等于,直接插入到后面 } else if(ret === 0){ return insertBetween(data, previous, current); // 如果小于则插入到前节点和当前节点中 // 因为已经是排序了,所以不需要多余判断了 } else { if(this.head === previous && previous === current){ return this.insertAsFirst(data); } else { return insertBetween(data, previous, current); } } } // 插入到最后一个结点 previous.next = this.makeNode(data); this.tail = previous.next; function insertBetween(data, a, b){ var temp = me.makeNode(data); temp.next = b; a.next = temp; return true; } } }; /* var list = new List(); list.add('b'); list.insertAsFirst('a'); list.insertAfter('b', 'c'); console.log(list.item(2)); console.log(JSON.stringify(list)); list.each(function (node) { if (node.data === 'b') { console.log('get b in each'); } }); list['delete']('c'); list['delete']('a'); console.log(list); var list2 = new List(); list2.add('c'); list2.insertAsFirst('d'); list2.insertAfter('d', 'b'); console.log(JSON.stringify(list2)); var list3 = List.mergeList(list, list2); console.log(list3); */ /* var list = new List(); list.orderInsert('e'); list.orderInsert('b'); list.orderInsert('c'); list.orderInsert('a'); list.orderInsert('d'); list.orderInsert('f'); */ }(this.module || this));
以下是对应的单元测试代码:
describe('linkedList tests', function(){ var list = new List(); it('should find the second item', function(){ list.add('b'); expect(list.head.data).toBe('b'); expect(list.tail.next).toBe(null); list.insertAsFirst('a'); expect(list.head.data).toBe('a'); expect(list.head.next.data).toBe('b'); list.insertAfter('b', 'c'); expect(list.item(2).data).toBe('b'); expect(list.tail.data).toBe('c'); }); it('should remove one item', function(){ expect(list['delete']('c')).toBe(true); list['delete']('a'); expect(list.head.data).toBe('b'); }); var list2 = new List(); it('should match the json', function(){ list2.add('c'); list2.insertAsFirst('d'); list2.insertAfter('d', 'b'); expect(JSON.stringify(list2)).toBe('{"head":{"data":"d","next":{"data":"b","next":{"data":"c","next":null}}},"tail":{"data":"c","next":null}}'); }); it('should merge the lists', function(){ var list3 = List.mergeList(list, list2); expect(list3.head.data).toBe('d'); expect(list3.head.next.data).toBe('b'); expect(list3.head.next.next.data).toBe('c'); expect(list3.tail.data).toBe('b'); }); });
相关文章推荐
- javascript实现数据结构与算法系列:循环链表与双向链表
- javascript实现数据结构与算法系列:栈 -- 顺序存储表示和链式表示及示例
- javascript实现数据结构与算法系列:队列 -- 链队列和循环队列实现及示例
- javascript实现数据结构与算法系列
- JavaScript开发——加载在线图片完整功能实现方法(正在加载-加载成功-加载失败)
- [JavaScript] 你相信么,只需一个函数5行JS代码即可在Javascript中实现完整的AOP功能,
- 你相信么,只需一个函数5行JS代码即可在Javascript中实现完整的AOP功能
- javascript实现数据结构与算法系列:线性表的静态单链表存储结构
- JavaScript实现--中英语言切换功能
- JavaScript实现列表分页功能特效
- Javascript动画系列之 —— lightbox实现(一)
- 数据结构与算法(C#实现)系列
- vb.net 实现javascript中的Eval功能
- 运用javascript的成员访问特性来实现通用版的兼容所有浏览器的打开对话框功能
- JavaScript实现翻页功能
- Java中实现FTP上传下载文件的功能,完整代码
- javascript的数组元素,为Array增加两个函数,实现删除功能
- 网页瀑布流布局实现方法及功能扩展(附完整代码)
- JavaScript使用execCommand实现浏览器的注销功能
- C# WinForm 实现增删改查等功能(Access版) 系列之三-更新