1. 程式人生 > >第三章列表

第三章列表

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