使用javascript模拟常见数据结构(二)
四、链表
每种语言都实现了数组。这种数据结构非常方便,提供了一个便利的[]语法来访问它的元素。然而,这种数据结构有一个缺点:(在大多数语言中)数组的大小是固定的,从数组的起点或中间插入或移除项的成本很高,因为需要移动元素 。链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。下图展示了一个链表的结构:
相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。然而,链表需要使用指针,因此实现链表时需要额外注意。数组的另一个细节是可以直接访问任何位置的任何元素,而要想访问链表中间的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素。
首先,我们来创建一个链表:
function LinkedList() { var Node = function(element){ // {1} this.element = element; this.next = null; }; var length = 0; // {2} var head = null; // {3} this.append = function(element){}; this.insert = function(position, element){}; this.removeAt = function(position){}; this.remove = function(element){}; this.indexOf = function(element){}; this.isEmpty = function() {}; this.size = function() {}; this.toString = function(){}; this.print = function(){}; }
如上所示,这是链表的追加元素的方法,如果头指针指向了空,那证明还没有元素,加入元素作为第一个元素,如果有元素,则找到链表的最后一个元素,使他的next指向加入的元素。
this.removeAt = function(position){ //检查越界值 if (position > -1 && position < length){ var current = head, previous, index = 0; //移除第一项 if (position === 0){ head = current.next; } else { while (index++ < position){ previous = current; current = current.next; } //将previous与current的下一项链接起来:跳过current,从而移除它 previous.next = current.next; } current.next = null; length--; return current.element; } else { return null; } };
那,这个是删除元素,就不用赘述了吧。
this.insert = function(position, element){ //检查越界值 if (position >= 0 && position <= length){ var node = new Node(element), current = head, previous, index = 0; if (position === 0){ //在第一个位置添加 node.next = current; head = node; } else { while (index++ < position){ previous = current; current = current.next; } node.next = current; previous.next = node; } length++; //更新列表的长度 return true; } else { return false; } };
恩,按照位置插入的代码也放在这里,请叫我雷锋,哈哈。
五、集合
集合是由一组无序且唯一(即不能重复)的项组成的。这个数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中。
下面我们来创建一个集合,其实ES6里面已经有了SET和MAP了,可以用babel转换的话直接写es6也是很好的。
function Set() { var items = {}; this.has = function(value){}; this.add = function(value){};
this.remove = function(value){};
this.clear = function(){};
this.size = function(){};
this.values = function(){};
}
相信上面的代码大家看到名字基本就明白了,恩,照例贴一些代码,Object.keys方法简直是神器呀。
this.has = function(value){ return items.hasOwnProperty(value); };
this.add = function(value){ if (!this.has(value)){ items[value] = value; return true; } return false; };
this.remove = function(value){ if (this.has(value)){ delete items[value]; //{2} return true; } return false; };
this.clear = function(){ items = {}; };
this.size= function(){ var count = 0; for(var prop in items) { if(items.hasOwnProperty(prop)) { ++count; } } return count; };
this.values = function(){ return Object.keys(items); };
好的,今天就说这么多,下回继续~