JavaScript数据结构 (手打代码)

时间:2023-03-10 02:19:53
JavaScript数据结构 (手打代码)

array:

数组创建:

var troop=new Array();                    //创建一个长度为6的数组
var troop=new Array(,,,,,);

数组方法:

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);
}
};
};