溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JS中的算法與數(shù)據(jù)結(jié)構(gòu)之列表(List)實(shí)例詳解

發(fā)布時(shí)間:2020-10-22 12:14:20 來源:腳本之家 閱讀:186 作者:Cryptic 欄目:web開發(fā)

本文實(shí)例講述了JS中的算法與數(shù)據(jù)結(jié)構(gòu)之列表(List)。分享給大家供大家參考,具體如下:

前言

前端很少有機(jī)會(huì)接觸到算法,大多都交互性的操作,所以不少前端工程師會(huì)抱著這么一種想法:我是做前端的,為什么要學(xué)數(shù)據(jù)結(jié)構(gòu)與算法?沒有數(shù)據(jù)結(jié)構(gòu)與算法,我一樣很好的完成工作。實(shí)際上,算法是一個(gè)寬泛的概念,我們平時(shí)寫的任何代碼都可以成為算法,它是對(duì)一個(gè)問題的解決方案的準(zhǔn)確而完整的描述,是解決一系列問題的清晰指令,它代表著用系統(tǒng)的方法描述解決問題的策略機(jī)制。隨著現(xiàn)在互聯(lián)網(wǎng)的飛速發(fā)展,前端工程師已不是靠幾個(gè)選擇器操作加鏈接加事件就能應(yīng)付的,越來越復(fù)雜的產(chǎn)品和基礎(chǔ)庫,需要堅(jiān)實(shí)的數(shù)據(jù)結(jié)構(gòu)與算法才能駕馭,所以我認(rèn)為前端工程師也是應(yīng)該要重視算法和數(shù)據(jù)結(jié)構(gòu),這對(duì)于自己的職業(yè)發(fā)展是有很大幫助的。當(dāng)然,算法的學(xué)習(xí)也不是一朝一夕的事情,這是一個(gè)過程,得自己去摸索,去實(shí)踐,去總結(jié),我這里只是將一些常見的算法和數(shù)據(jù)結(jié)構(gòu)用 JavaScript 去實(shí)現(xiàn),起到一個(gè)拋磚引玉的作用。


列表(List)

列表是計(jì)算機(jī)中一種常見的數(shù)據(jù)結(jié)構(gòu),日常生活中的購物清單,待辦事項(xiàng)等都可以成為列表,它是一組有序的數(shù)據(jù),每個(gè)列表中的數(shù)據(jù)項(xiàng)稱為元素。在javascript中,列表中的元素可以是任意數(shù)據(jù)類型。列表中可以保存多少元素并沒有限定(在實(shí)際使用時(shí)會(huì)受到程序內(nèi)存的限制)。列表中會(huì)有一些常見屬性或方法,比如列表中的元素個(gè)數(shù),列表當(dāng)前的位置,向列表末尾增加一個(gè)元素,從列表中刪除一個(gè)元素,清空列表等一系列操作。接下來,我們抽象出一個(gè)列表的數(shù)據(jù)類型定義,并用JS中的數(shù)組去實(shí)現(xiàn)它。

JS中的算法與數(shù)據(jù)結(jié)構(gòu)之列表(List)實(shí)例詳解 
列表的數(shù)據(jù)類型定義

列表類

/*定義List類*/
 function List () {
  this.listSize = 0;  //初始化元素個(gè)數(shù)為0
  this.pos = 0;    //初始化位置為0
  this.dataStore = []; //初始化空數(shù)組來保存列表元素
  this.clear = clear;
  this.find = find;  //尋找元素
  this.toString = toString; //顯示列表中的元素
  this.insert = insert;
  this.append = append;
  this.remove = remove;
  this.front = front;
  this.end = end;
  this.prev = prev;
  this.next = next;
  this.length = length; //列表中的元素總數(shù)
  this.currPos = currPos;
  this.moveTo = moveTo;
  this.getElement = getElement;
  this.contains = contains; //判斷給定值是否在列表中
}

接著我們來實(shí)現(xiàn)這些方法。

首先得可以添加元素,所以我們先來編寫 append 方法

append:向列表中添加一個(gè)元素

//該方法給列表的最后一個(gè)位置添加一個(gè)新的元素,待插入成功后,更新列表中的元素個(gè)數(shù)

function append ( element ) {
  this.dataStore[this.listSize++] = element;
}

這樣我們就可以往列表里面添加元素了,接著我們來看查找 find 方法

find:查找列表中的某一個(gè)元素

//該方法通過循環(huán)查找給定元素是否在列表中,如果存在返回元素的位置,否則返回 -1

function find(element){
  for( var i = 0 ; i < this.dataStore.length ; i ++ ){
      if( this.dataStore[i] == element ){
        return i;
      }
    }
  return -1;
}

可以插入元素,那總得可以刪除了,我們利用 remove 方法刪除一個(gè)元素

remove:刪除列表中的某一元素

//該方法通過使用find()方法返回元素的位置對(duì) dataStore 數(shù)組進(jìn)行截取,如果刪除成功,返回 true , 并將 listSize 的值減1,更新列表長度,否則返回 false

function remove ( element ) {
  var foundAt = this.find(element);
  if( foundAt > -1 ){
    this.dataStore.splice( foundAt , 1 );
    --this.listSize;
    return true;
  }
  return false;
}

我想知道我的列表還有多少個(gè)元素的時(shí)候,就得構(gòu)建 length 方法,

length:返回列表中總的元素個(gè)數(shù)

//該方法直接將 listSize 返回即可

function length(){
  return this.listSize;
}

如果能顯示我的列表元素就好了,這個(gè)可以有,我們來看看 toString 方法,

toString:顯示列表的元素

//該方法直接返回了列表數(shù)組,顯示出當(dāng)前列表內(nèi)容

function toString(){
  return this.dataStore;
}

現(xiàn)在我們的列表已經(jīng)有了基本的一些功能,不妨下試試

//構(gòu)造列表對(duì)象
var fruits = new List();
//添加三個(gè)元素
fruits.append('Apple');
fruits.append('Grape');
fruits.append('Banana');

//打印列表
console.log( fruits.toString() )   // ["Apple", "Grape", "Banana"]
//查看列表長度
console.log( fruits.length() )    // 3
//查找 Banana 的位置
console.log( fruits.find('Banana') ) // 2
//刪除 Grape 
fruits.remove('Grape');
console.log( fruits.toString() )   // ["Apple", "Banana"]

如果我們刪除了 Grape 元素 , 我們還想將它放回到原來的位置 ,這時(shí)候我們就需要調(diào)用 insert 方法

insert:向列表某個(gè)位置添加一個(gè)元素

//該方法需要傳入兩個(gè)參數(shù),第一個(gè)參數(shù)表示待插入的元素,第二個(gè)參數(shù)表示待插入元素的前一個(gè)元素,用于確定插入元素的位置,并調(diào)用 splice 方法更改列表數(shù)組,插入成功后更新 listSize 并返回 true , 否則返回 false;
function insert( element , after ){
  var insertPos = this.find( after );
  if( insertPos > -1 ){
    this.dataStore.splice( insertPos + 1 , 0 , element );
    this.listSize ++;
    return true;
  }
  return false;
}

現(xiàn)在,我們把 Grape 放到原來的位置上去;

fruits.insert( 'Grape' , 'Apple' );
console.log( fruits.toString() )    // ["Apple", "Grape", "Banana"]

ok,現(xiàn)在已經(jīng)能夠把 Grape 插入到原來的位置了。

如果我吃完了所有水果,我現(xiàn)在想要清空列表,我們就需要一個(gè) clear 方法;

clear:清空列表

//該方法使用 delete 操作符刪除 dataStore 數(shù)組 , 接著創(chuàng)建新的數(shù)組,并將其 listSize 和 pos 初始化設(shè)為 1 。

function clear(){
  delete this.dataStore;
  this.dataStore = [];
  this.listSize = this.pos = 0;
}

我們不妨試一試。

fruits.clear();
console.log( fruits.toString() );   // []

成功了!

上面我們看到了列表中有個(gè) pos 屬性,表示當(dāng)前列表所在的位置,我們接下來就圍繞它做點(diǎn)事情,讓用戶可以自由操作列表

front:將列表的位置移到第一個(gè)位置上

//該方法只要將 pos 置為 0 即可

function front(){
  this.pos = 0 ;
}

end:將列表的位置移到最后一個(gè)位置上

//同上,該方法只要將 pos 置為列表長度減 1 即可,因?yàn)閿?shù)組下標(biāo)從 0 開始嘛

function end(){
  this.pos = this.listSize - 1;
}

prev:將當(dāng)前位置前移一位

//只要將 pos 的位置減 1 即可,但要主要不能越界

function prev(){
  if( this.pos > 0 ){
    this.pos --;
  }else{
    console.log('您當(dāng)前已在首位');
  }
}

next:將當(dāng)前位置后移一位

//同理,只要將 pos 的位置加 1 即可,但要主要不能越界

function next(){
  if( this.pos < this.listSize - 1 ){
    ++this.pos;
  }else{
    console.log('您當(dāng)前已在末尾');
  }
}

moveTo:將當(dāng)前位置移動(dòng)到指定位置

//直接改變 pos 的值即可,注意輸入的合法性

function moveTo( position ){
  if( position < 0 || position > (this.listSize - 1) ){
    console.log('請(qǐng)輸入正確的位置');
  }else{
    this.pos = position;
  }
}

我既然可以隨意改變我的列表位置,那我總得知道我當(dāng)前位置在哪里啊,因此我們需要 currPos 和 getElement 兩個(gè)方法分別返回當(dāng)前的位置和元素;

currPos:返回列表的當(dāng)前位置

//只需將 pos 直接返回即可

function currPos(){
  return this.pos;
}

getElement:返回當(dāng)前位置的元素

//直接取對(duì)應(yīng)的元素就好

function getElement(){
  return this.dataStore[this.pos];
}

接著,我們測試一下,首先將列表恢復(fù)到清空前的樣子,然后我們?cè)诙嗵砑訋讉€(gè)元素進(jìn)去。

//再添加幾個(gè)
fruits.append('Pear');
fruits.append('Orange');
fruits.append('Strawberry');
console.log( fruits.toString() );  // ["Apple", "Grape", "Banana", "Pear", "Orange", "Strawberry"]

//我們先看當(dāng)前的位置和元素
console.log( fruits.currPos() );   // 0
console.log( fruits.getElement() ); // Apple

//我們嘗試改變一下
fruits.moveTo( 2 );
fruits.next();
console.log( fruits.currPos() );   // 3
console.log( fruits.getElement() ); // Pear
fruits.end();
fruits.prev();
console.log( fruits.currPos() );   // 4
console.log( fruits.getElement() ); // Orange

至此,我們已經(jīng)基本完成了列表的所有功能,還差最后一個(gè),判斷給定元素是否在列表內(nèi),我們這里采用 contains 方法

contains:判斷給定值是否在列表中

//我們直接利用利用 indexOf() 或者采用跟為高級(jí)的 ES6 中的 includes 方法來判斷

//ES5
function contains( element ){
  if( this.dataStore.indexOf( element ) > -1 ) return true;
  else return false;
}

//ES6

function contains( element ){
  return this.dataStore.includes( element );
}

( ps:對(duì) ES6 不太熟悉的同學(xué),也可以參考本站https://www.jb51.net/article/138409.htm )

寫完測試一下,

console.log(fruits.contains('Banana'));     // true
console.log(fruits.contains('Watermelon'));   // false

大功告成!我們自己用 javascript 實(shí)現(xiàn)了一個(gè)列表,至于后面如何拓展,自己可以發(fā)散思維,多動(dòng)手實(shí)踐實(shí)踐,一起加油!

感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼運(yùn)行效果。

更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript數(shù)組操作技巧總結(jié)》、《JavaScript排序算法總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》及《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》

希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI