array:
数组创建:
var troop=new Array(6); //创建一个长度为6的数组 var troop=new Array(2,3,5,6,4,7);
数组方法:
var str="I love javascript"; var single=str.split(""); //'I',' ','l','o',..... var mutipy=str.split(" "); //'I','love','javascript' var troop=new Array(2,5,6,8,9,4,1,2); var index=troop.indexOf(2); //index=0 var names=['jack','mike','molly']; var str=names.join(); //str='jack,mike,molly' var nums=[]; nums.push(3,4); nums.shift(1,2); //nums=[1,2,3,4]; nums.pop(); //nums=[1,2,3]; nums.shift(); //nums=[2,3]; nums.splice(0,1,5,6) //nums=[5,6,3];
对数组元素进行操作(不产生新数组) var nums=[2,4,6,8]; function isEven(num){return num%2==0;}
function square(num){return num*num;}
nums.forEach(square); //对数组所有元素平方
var swit=nums.every(isEven); //判断数组元素是否均为偶数,若是,返回true;
产生新数组:
filter,map
二元数组:
for(var i=0;i<5;i++)
troop[i]=[];
栈和列表其实就是对数组和数组方法的封装,所以我省略不写。
链表:
var linkLIst=function(){ var Node=function(element){ this.element=element; this.next=null; }; this.length=0; this.head=new Node("head"); //定义链表头,长度,同时,定义了四个方法。 this.append=append; this.insert=insert; this.remove=remove; this.display=display; function append(element){ var newNode=new Node(element); //链表在末尾添加新节点,注意的是,node.next仍是node类型,故在添加新节点时要调用节点构造函数 var thisNode=this.head;
this.length++; if(thisNode.element==null) //在写循环语句或者判断语句的时候要注意,一个空节点是没有element元素的, { //因此要先确保thisNode为非空节点,该if判断语句才能正常运行,不然会报错。 thisNode.element=element; }else{ while(thisNode.next) { thisNode=thisNode.next; } thisNode.next=newNode; } }; function insert(elementbe,element){ var nodebe=this.head; this.length++; var insertNode=new Node(element); while(!(nodebe.element===elementbe)){ nodebe=nodebe.next; }; var nodeafter=nodebe.next; nodebe.next=insertNode; insertNode.next=nodeafter; }; function remove(element){ var nodeDelete=this.head; while(!(nodeDelete.next.element===element)) { nodeDelete=nodeDelete.next; }; var nodeAfter=nodeDelete.next.next; //next可叠加多次 nodeDelete.next=nodeAfter; }; function display(){ var thisNode=this.head; var str=""; while(thisNode){ str+=thisNode.element+" "; thisNode=thisNode.next; } return str; } }; var newlist=new linkLIst(); //如果调用构造函数为什么用new不太理解,可以参考上一篇博文我对this的简析 newlist.append("1");newlist.append("2");newlist.append("3");newlist.append("4");newlist.insert("3","5") var str=newlist.display(); alert(str);
字典:字典类型实际上和数组差不多,但要关注的是,字典类型的键通常为字符串,不是像数组中从0递增,因此,在展示全部元素时与数组有所区别
var myDictionary=function(){
this.dataStore=new Array(); this.add=add; this.find=find; this.showAll=showAll; this.remove=remove; function add(key,value){ this.dataStore[key]=value; }; function find(key){ return this.dataStore[key]; }; function remove(key){ delete this.dataStore[key]; //这个方法只删除key对应的值 }; function showAll(){ var arr=new Array(),i=0; for (var key in this.dataStore) //key实际上是数组里面的元素? { //某本书上有错误的范例(var key in Object.keys(this.dataStore)),该语句中key的值为0,1,2,3....故只适用于一般数组 arr[i++]=key+" "+this.dataStore[key]; } return arr; }; }; var dict=new myDictionary(); dict.add("one","Mike");dict.add("two","John");dict.add("three","Molly"); var show=dict.showAll(); alert(show);
hash table(散列表):
var hashTable=function(){ this.table=new Array(137); //先定义表的大小,因为后面的哈希值要通过表大小来确定 this.simpleHash=simpleHash; //求得哈希值 this.showDistro=showDistro; //展示所有元素,返回一个字符串 this.put=put; //将新元素加入表中 function simpleHash(data){ var hash=0; for(var i=0;i<data.length;i++) { hash+=data.charCodeAt(i); //函数charCodeAt()返回字符串某个元素的ASC码值,这里用循环得到字符串ASC码值之和 } return hash % 137; //将码值之和除以表大小,所得余数为键,这样可以确保键的数值大小始终小于表的大小 }; function showDistro(){ var i=0; str=""; while(i++<this.table.length) { if(this.table[i]!=null) //由上面哈希表创建过程可知哈希表有一些键值是未定义的,因此要过滤掉这些元素 { str+=i+" "+this.table[i]+" ."; } } return str; }; function put(data){ var i=simpleHash(data); this.table[i]=data; }; }; var tab=new hashTable(); tab.put("abc");tab.put("sdf"); var output=tab.showDistro(); alert(output);
分析上面代码,可以发现一个问题,两个字符串asc码值之和相同,那么后者会把前者覆盖,这个问题有三种解决方法,一为将hash值转换过程改善,通常采用的是与等比数列相乘,二为在哈希表中创建链表,这样,即使哈希值相同,所有的元素都能展现,三为将后来者往下移,填补到空缺的位置。
function betterHash(data){ //第一种方法。 var hashNum=0; //用betterHash代替原有方法,可以使数据更分散。 for(var i=0;i<data.length;i++){ hashNum=data.charCodeAt(i)+hashNum*37 //注意的是这里要乘一个质数,当然,不同的质数效果不同,实际情况要多次实验? } return hashNum; }
二叉树:
var BST=function(){ this.root=null; this.add=add; this.remove=remove; this.showAll=showAll; var Node=function(data,left,right){ this.data=data; this.left=left; this.right=right; }; function add(data){ var newNode=new Node(data,null,null) if(this.root===null){ this.root=newNode; }else{ var lastNode=this.root; while(lastNode){ if(data>lastNode.data){ //按数据大小排序 if(lastNode.right!=null){ lastNode=lastNode.right; }else{ lastNode.right=newNode;return; } }else{ if(lastNode.left!=null){ lastNode=lastNode.left; }else{ lastNode.left=newNode;return; } } }; } }; function remove(data){ var deleteNode=this.root; while(deleteNode){ if(deleteNode.data>data){ deleteNode=deleteNode.left; }else if(deleteNode.data<data){ deleteNode=deleteNode.right; }else if(deleteNode.data===data){ deleteNode=null; } }; }; function putStr(data){ var newInsert=$("<p></p>"); newInsert.html(data); $("body").append(newInsert); }; function showAll(Node) { if (!(Node.data === null)) { putStr(Node.data); //此句放前为先序,放中间为中序,放后面为后序 if(Node.left!=null){ showAll(Node.left); } if(Node.right!=null){ showAll(Node.right); } } return; }; }; var tt=new BST(); tt.add(2);tt.add(3);tt.add(7);tt.add(1);tt.add(9);tt.add(4);tt.add(5);alert(tt.root.data); tt.showAll(tt.root);
二叉树的难点是遍历,由于二叉树只有向下通道,而没有向上通道,所以一般采用迭代遍历。
图:图的难点在于深度搜索算法和广度搜索算法的实现
var Graph=function (v){ this.vertices=v; //顶点个数 this.edges=0; //边的条数 this.adj=[]; //下面是深度,广度搜索算法实现的条件,将所有元素先标记为未访问。 this.mark=[]; for(var i=0;i<this.vertices;i++){ this.mark[i]=false; } // for(var i=0;i<this.vertices;i++){ this.adj[i]=[]; //将每个顶点相邻元素放入一个数列,则一共有V个数列,并且,数列长度必小于V } this.add=add; this.showGraph=showGraph; this.deepSearch=deepSearch; this.wideSearch=wideSearch; function add(v,w){ this.adj[v].push(w); //这个图类是无指向性的图。 this.adj[w].push(v); this.edges++; }; function putStr(data){ var str=$("#output").html(); str+=data; $("#output").html(str); }; function showGraph(){ for(var i=0;i<this.vertices;i++){ putStr(i+" ->"); for(var j=0;j<this.vertices;j++){ if(this.adj[i][j]!=null){ putStr(this.adj[i][j]+" "); } } putStr('|'); } }; function deepSearch(v){ this.mark[v]=true; putStr("mark:"+v+"visited!"); //深度搜索算法中,从顶端元素一直探索到最远路径,然后,再探索另一条路径。 alert(this.adj[v]); //实现方法也较为简单,依次递归调用函数取得当前元素相邻、未访问过的元素,这样,可以得到最深的图。 for (var i=0;i<this.adj[v].length;i++){ if(this.mark[this.adj[v][i]]!=true){ this.deepSearch(this.adj[v][i]); } } }; function wideSearch(v){ var queue=[]; queue.push(v); this.mark[v]=true; for(var i=0;i<this.adj[v].length;i++){ //广度搜索算法中,先遍历与首元素相邻的元素,再遍历与这些元素相邻的元素,用队列可以完美解决这个问题,先将一级相邻元素 if(this.mark[this.adj[v][i]]!=true){ //放入队列中,然后挨个取出队列元素,将队列元素的相邻元素也放入队列中。 queue.push(this.adj[v][i]); alert("push"+" "+this.adj[v][i]); this.mark[this.adj[v][i]]=true; } } putStr(queue.shift()); if(queue[0]!=null){ var out=queue.shift(); this.wideSearch(out); } }; };