第三章列表
1.列表的抽象数据类型定义
listSize(属性) 列表的元素个数pos (属性) 列表的当前位置
length (属性) 返回列表中元素的个数
clear (方法) 清空列表中的所有元素
find (方法) 在列表中查找某一元素
toString (方法) 返回列表的字符串形式
getElement (方法) 返回当前位置的元素
insert (方法) 在现有元素后插入新元素
append (方法) 在列表的末尾添加新元素
remove (方法) 从列表中删除元素
front (方法) 将列表的当前位置设移动到第一个元素
end (方法) 将列表的当前位置移动到最后一个元素
prev(方法) 将当前位置前移一位
next (方法) 将当前位置后移一位
currPos (方法) 返回列表的当前位置
moveTo(方法) 将当前位置移动到指定位置
contains (方法) 判断给定值是否在列表中
function List(){ this.dataStore=[];//初始化一个空数组来保存列表元素 this.listSize=0; this.pos=0; this.length=length; this.clear=clear; this.find=find; this.toString=toString; this.getElement=getElement; this.insert=insert; this.append=append; this.remove=remove; this.front=front; this.end=end; this.prev=prev; this.next=next; this.currPos=currPos; this.moveTo=moveTo; this.contains=contains; } //返回列表元素的个数 function length(){ return this.listSize; } //清空列表中所有的元素 function clear(){ delete this.dataStore; this.dataStore=[]; this.listSize=this.pos=0; return this.dataStore; } //在列表中查找某一元素 function find(element){ for(let i=0;i<this.dataStore.length;i++){ if (element ==this.dataStore[i] ) { return i; } } return -1; } //显示列表中的元素 function toString(){ return this.dataStore; } //返回当前位置的元素 function getElement(){ return this.dataStore[this.pos]; } //向列表中插入一个元素 function insert(element,after){ let insertPos; if(after==null){ insertPos=this.dataStore.length-1; }else{ insertPos=this.find(after); } if(insertPos>-1){ this.dataStore.splice(insertPos+1,0,element); this.listSize++; return true; } return false; } //给列表添加元素 function append(element){ this.dataStore[this.listSize++]=element; return this.listSize; } //从列表中删除元素 function remove(element){ let foundAt=this.find(element); if (foundAt>-1) { this.dataStore.splice(foundAt,1); --this.listSize; return true; } return false; } //将列表的当前位置设移动到第一个元素 function front(){ this.pos=0; } //将列表的当前位置设移动到第一个元素 function end(){ this.pos=this.listSize-1; } //将当前位置前移一位 function prev(){ if(this.pos>=0){ this.pos--; } } //将当前位置后移一位 function next(){ if(this.pos<this.listSize){ this.pos++; } } //返回列表的当前位置 function currPos() { return this.pos; } //将当前位置移动到指定位置 function moveTo(position) { this.pos=position; } //判断给定值是否在列表中 function contains(element) { if(this.find(element)==-1){ return false; } return true; } let names=new List(); names.append("Cynthia"); names.append("Raymond"); names.append("Barbara"); console.log(names.toString());//[ 'Cynthia', 'Raymond', 'Barbara' ] names.remove("Raymond"); console.log(names.toString());//[ 'Cynthia', 'Barbara' ] names.insert("blsm"); console.log(names.toString());//[ 'Cynthia', 'Barbara', 'blsm' ] let flag=names.contains('bls'); console.log(flag);//false names.front(); console.log(names.getElement());//Cynthia names.next(); console.log(names.getElement());//Barbara //以下是和使 用数组索引的方式相比,使用迭代器的一些优点。 //1.访问列表元素时不必关心底层的数据存储结构。 //2.当为列表添加一个元素时,索引的值就不对了,此时只用更新列表,而不用更新迭代器。 //3.可以用不同类型的数据存储方式实现List 类,迭代器为访问列表里的元素提供了一种统一的方式 console.log("迭代器遍历"); for(names.front();names.currPos()<names.length();names.next()){ console.log(names.getElement()); } console.log("迭代器从后向前遍历"); for(names.end();names.currPos()>=0;names.prev()){ console.log(names.getElement()); } names.clear(); console.log(names.toString());//[]
2.基于列表的实际应用
为了展示如何使用列表,我们将实现一个类似 Redbox 的影碟租赁自助查询系统。为了得到商店内的影碟清单,我们需要将数据从文件中读进来。films.txt文件数据内容如下:
(1) The Shawshank Redemption(《肖申克的救赎》)
(2) The Godfather(《教父》)
(3) The Godfather: Part II(《教父 2》)
(4) Pulp Fiction(《低俗小说》)
(5) The Good, the Bad and the Ugly(《黄金三镖客》)
(6) 12 Angry Men(《十二怒汉》 )
(7) Schindler’s List(《辛德勒名单》)
(8) The Dark Knight(《黑暗骑士》)
(9) The Lord of the Rings: The Return of the King(《指环王:王者归来》)
(10) Fight Club(《搏击俱乐部》)
(11) Star Wars: Episode V - The Empire Strikes Back(《星球大战 5:帝国反击战》)
(12) One Flew Over the Cuckoo’s Nest(《飞越疯人院》)
(13) The Lord of the Rings: The Fellowship of the Ring(《指环王:护戒使者》)
(14) Inception(《盗梦空间》)
(15) Goodfellas(《好家伙》)
(16) Star Wars(《星球大战》)
(17) Seven Samurai(《七武士》)
(18) The Matrix(《黑客帝国》)
(19) Forrest Gump(《阿甘正传》)
(20) City of God(《上帝之城》
读取文件使用到node中fs模块的函数,需要fs模块。并将上文的列表函数通过module.exports=List;暴露出去
const fs=require('fs');//调用fs函数库 const List=require('./lesson2-1.js');//调用List //异步读取 /*fs.readFile('films.txt','utf-8',function(err,data){ if (err) { console.error(err); }else{ console.log(data); } });*/ //同步读取 // let movies=fs.readFileSync('films.txt','utf-8').split("\n"); // console.log(movies); //读取的内容被分割成数组后,换行符被替换成空格。空格在比较字符串时有许多问题 //使用trim方法删除每个数组元素未尾的空格 function createArr(file){ let arr=fs.readFileSync(file,'utf-8').split("\n"); for(let i=0;i<arr.length;i++){ arr[i]=arr[i].trim(); } return arr; } //新列表customers let customers=new List(); function Customer(name,movice){ this.name=name; this.movice=movice; } //该函数有两个参数:客户姓名和客户想 要检出的电影。 //如果该电影目前可以租赁,该方法会从影碟店的影碟清单里删除该元素, //同时加入客户列表 customers。 function checkOut(name,movice,moviceList,customerList){ if(moviceList.contains(movice)){ let c=new Customer(name,movice); customerList.append(c); moviceList.remove(movice); }else{ console.log(movice+"暂时没有"); } } //显示清单 function displayList(list){ for(list.front();list.currPos()<list.length();list.next()){ if (list.getElement() instanceof Customer) { console.log(list.getElement()["name"]+","+ list.getElement()["movice"]); }else{ console.log(list.getElement()); } } } //测试 let movies=createArr('films.txt'); let movieList=new List(); let customerList=new List(); for(let i=0;i<movies.length;i++){ movieList.append(movies[i]); } console.log("所有的电影:"); displayList(movieList); checkOut("blsm","(14) Inception(《盗梦空间》)",movieList,customerList); console.log("\n客户清单:"); displayList(customerList);
3.列表练习习题
1)增加一个向列表中插入元素的方法,该方法只在待插元素大于列表中的所有元素时才执行插入操作。这里的大于有多重含义,对于数字,它是指数值上的大小;对于字母,它是指在字母表中出现的先后顺序。
const List=require('./lesson2-1.js');//调用List function infix(elelment){ for(this.front();this.currPos()<this.length();this.next()){ if(elelment<=this.getElement()){ return false; } } this.append(elelment); return this.dataStore; } let test=new List(); test.infix=infix; test.append(1); test.append(2); test.append(3); test.append('a'); console.log(test.toString()); console.log(test.infix('a'));
2)为影碟租赁程序创建一个 check-in() 函数,当客户归还一部影片时,将该影片从已租列表中删除,同时添加到现有影片列表中。因为涉及到对象的比较,在这里使用underscore.js的isEqual方法,在lesson2-1.js中引入underscore.js,对find()做出如下修改
//在列表中查找某一元素 function find(element){ for(let i=0;i<this.dataStore.length;i++){ if (_.isEqual(element,this.dataStore[i])) { return i; } } return -1; }
在lesson2-2.js中添加checkIn方法 //当客户归还一部影片时,将该影片从客戶列表中删除,同时添加到现有影片列表中。 function checkIn(name,movice,movieList,customerList){ let c=new Customer(name,movice); if(customerList.contains(c)){ movieList.append(movice); customerList.remove(c); }else{ console.log(name+" 沒有租借 "+movice); } }