數據結構與算法JS實現

 

行解算法題,沒錯,就是這麼方便。javascript

固然也可使用 Node.js 環境來執行,具體參考Node.js官方文檔便可。java

二 對象和麪向對象編程

js中5種數據類型,並無定義更多的數據類型,可是運用js中一切皆對象的思想,能夠本身很方便的去構造出各類複雜的數據類型對象。node

這裏討論到的數據結構都被實現爲對象。 JavaScript 提供了多種方式來建立和使用對象。 這裏經過以下方式建立:算法

定義包含屬性和方法聲明的構造函數, 並在構造函數後緊跟方法
的定義。 編程

下面是一個檢查銀行帳戶對象的構造函數:數組

//該數據對象的構造函數,至關因而一個類 function Checking(amount) { this.balance = amount; // 屬性 this.deposit = deposit; // 方法 this.withdraw = withdraw; // 方法 this.toString = toString; // 方法 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

this 關鍵字用來將方法和屬性綁定到一個對象的實例上。 下面咱們看看對於前面聲明過的方法是如何定義的:markdown

function deposit(amount) { this.balance += amount; } function withdraw(amount) { if (amount <= this.balance) { this.balance -= amount; } if (amount > this.balance) { print("Insufficient funds"); } } function toString() { return "Balance: " + this.balance; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

使用時這樣:網絡

//注意這裏經過: new 構造函數(傳入的參數)生成了一個對象實例 var account = new Checking(500); account.deposit(1000); print(account.toString()); //Balance: 1500 account.withdraw(750); print(account.toString()); // 餘額: 750 account.withdraw(800); // 顯示 " 餘額不足 " print(account.toString()); // 餘額: 750
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

這就是一個定義數據對象的方法,下面構建各類數據結構也是使用這樣的方式(除過數組,由於js自己定義了數組類型;其次,其餘的數據結構的定義有不少事使用數據做爲基礎數據結構進行數據存儲的)。數據結構

三 數組

1.字符串分割爲數組split與數組元素拼接轉字符串join

var sentence = "the quick brown fox jumped over the lazy dog"; /**1. * 字符串.split(分隔符) 將字符串生成爲數組 * */ var words = sentence.split(" "); for (var i = 0; i < words.length; ++i) { print("word " + i + ": " + words[i]); } /**2. * 數組轉字符串 * .join(分隔符) * 數組各元素間放分隔符並鏈接成一個字符串 * join("") 就是 直接將數組個元素拼接起來生字符串 * .toString()鏈接成字符串後 默認中間會用,隔開 * */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2.indexOf-查找數組是否存在某元素及下標

var names = ["David","Cynthia","Raymond","Clayton","Jennifer"]; putstr("Enter a name to search for: "); var name = readline(); /**1. * 數組.indexOf(參數值) 參數值是否存在於數組, * 存,返第一個出現該元素的下標; * 不存,返-1; * * 數組.lastIndexOf(參數值) * 反序找第一個的下標(若是出現,不然返-1) * * */ var position = names.indexOf(name); if (position >= 0) { print("Found " + name + " at position " + position); } else { print(name + " not found in array."); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

3.數組中間添加和刪除修改元素splice

直接上代碼,總結見註釋:app

/** * 1.splice() 將現有數組進行截取,返回所截取生成出來的數組,且現有數組改變,是截取後的數組 * 可用於爲一個數組增長或移除或修改元素 * 參數一:截取(刪除)的起始索引(0是第一個元素) * 參數二:截取(刪除)的元素的個數 * 參數三:刪除截取後要添加進數組的元素(能夠是個數組) * */ /**2. * 數組中間插入元素(放在數組裏插入) * */ var nums = [1,2,3,7,8,9]; var newElements = [4,5,6]; nums.splice(3,0,newElements); print(nums); // 1,2,3,4,5,6,7,8,9 /**3. * 要插入數組的元素沒必要組織成一個數組, 它能夠是任意的元素序列 * */ var nums = [1,2,3,7,8,9]; nums.splice(3,0,4,5,6); print(nums); /**4. * 從數組中刪除元素 * */ var nums = [1,2,3,100,200,300,400,4,5]; nums.splice(3,4); print(nums); // 1,2,3,4,5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

4.不生成新數組的迭代器方法-forEach每一個元素都操做-every全部都知足-some有一個知足-reduce累計操做

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/13. */ /** * 1. 數組.forEach(func) 對數組每一個元素執行某操做 * 它接受一個函數做爲參數,對數組中的每一個元素使用該函數 * */ function squareFunc(num) { print(num, num * num); //打印多個字符的時候自動中間會加空格 } var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; nums.forEach(squareFunc); /** * 2. 數組.every(func), 檢查數組中每一個元素是否知足某條件 * 它接受一個返回值爲布爾類型的函數, 對數組中的每一個元素使用該函數。 * 若是對於全部的元素,該函數均返回 true, 則該方法返回 true * * 數組.some(func) * 是否存在一個元素知足 * 也接受一個返回值爲布爾類型的函數, 只要有一個元素使得該函數返回 true, * 該方法就返回 true * */ function isEven(num) { return num % 2 == 0; } var nums = [2, 4, 6, 8, 10]; var even = nums.every(isEven); if (even) { print("all numbers are even"); } else { print("not all numbers are even"); } /** * 3. * reduce() 數組中的各個元素累計進行操做 * 它接受一個函數, 返回一個值。 該方法會從一個累加值開始, 不斷對累加值和 * 數組中的後續元素調用該函數, 直到數組中的最後一個元素, 最後返回獲得的累加值。 * */ //使用 reduce() 方法爲數組中的元素求和: function add(runningTotal, currentValue) { return runningTotal + currentValue; } var nums = [1,2,3,4,5,6,7,8,9,10]; var sum = nums.reduce(add); // print(sum); // 顯示 55 //reduce() 方法也能夠用來將數組中的元素鏈接成一個長的字符串 function concat(accumulatedString, item) { return accumulatedString + item; } var words = ["the ", "quick ","brown ", "fox "]; var sentence = words.reduce(concat); print(sentence); // 顯示 "the quick brown fox" /** * 4.reduceRight() 方法,從右到左執行。 * 下面的程序使用 reduceRight() 方法將數組中的元素進行翻轉: * */ function concat(accumulatedString, item) { return accumulatedString + item; } var words = ["the ", "quick ","brown ", "fox "]; var sentence = words.reduceRight(concat); print(sentence); // 顯示 "fox brown quick the"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

5.生成新數組的迭代器方法-map每一個元素都執行某操做結果組成的數組-filter數組中知足某條件的元素組成的數組

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/13. */ /** * 1. 數組.map(func) * map() 和 forEach() 有點兒像, * 對數組中的每一個元素使用某個函數。 二者的區別是 * map() 返回一個新的數組, 該數組的元素是對原有元素應用某個函數獲得的結果 * */ function curve(grade) { return grade += 5; } var grades = [77, 65, 81, 92, 83]; var newgrades = grades.map(curve); print(newgrades); // 82, 70, 86, 97, 88 /** * 2.下面是對一個字符串數組使用 map() 方法的例子: * 數組 acronym 保存了數組 words 中每一個元素的第一個字母。 * 然而, 若是想將數組顯示爲真正的縮略形式, 必須想辦法除掉鏈接每一個數組元素的逗號, * 若是直接調用 toString() 方法, 就會顯示出這個逗號。 * 使用 join() 方法, 爲其傳入一個空字符串做爲參數, 則能夠幫助咱們解決這個問題 * */ function first(word) { return word[0]; } var words = ["for", "your", "information"]; var acronym = words.map(first); print(acronym) print(acronym.join("")); // 顯示 "fyi" /** * 3.filter() 傳入一個返回值爲布爾類型的函數。 * 和 every() 方法不一樣的是, * 當對數組中的全部元素應用該函數,該方法並不返回 true, * 而是返回一個新數組, 該數組包含應用該函數後結果爲 true 的元素。 * */ //下列程序篩選數組中的奇數和偶數元素 function isEven(num) { return num % 2 == 0; } function isOdd(num) { return num % 2 != 0; } var nums = []; for (var i = 0; i < 20; ++i) { nums[i] = i + 1; } var evens = nums.filter(isEven); print("Even numbers: "); print(evens); var odds = nums.filter(isOdd); print("Odd numbers: "); print(odds); //執行結果以下:Even numbers:2,4,6,8,10,12,14,16,18,20 Odd numbers:1,3,5,7,9,11,13,15,17,19 //下面使用 filter() 篩選全部成績及格的分數: function passing(num) { return num >= 60; } var grades = []; for (var i = 0; i < 20; ++i) { grades[i] = Math.floor(Math.random() * 101); } var passGrades = grades.filter(passing); print("All grades:"); print(grades); print("Passing grades: "); print(passGrades); //還可使用 filter() 方法過濾字符串數組,下面這個例子過濾掉了那些不包含「 cie」 的單詞: function afterc(str) { if (str.indexOf("cie") > -1) { return true; } return false; } var words = ["recieve","deceive","percieve","deceit","concieve"]; var misspelled = words.filter(afterc); print(misspelled); // 顯示 recieve,percieve,concieve
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

6.二維數組和多維數組

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/13. */ /** * 1.建立二維數組 * 比較好的方式是遵守 JavaScript: TheGood Parts( O’Reilly) 一書第 64 頁的例子, * 經過擴展 JavaScript 數組對象, 爲其增長了一個新方法, * 該方法根據傳入的參數, 設定了數組的行數、 列數和初始值 * */ Array.matrix = function(numrows, numcols, initial) { var arr = []; for (var i = 0; i < numrows; ++i) { var columns = []; for (var j = 0; j < numcols; ++j) { columns[j] = initial; } arr[i] = columns; } return arr; } //測試該生成二維數組方法的一些測試代碼 var nums = Array.matrix(5,5,0); print(nums[1][1]); // 顯示 0 var names = Array.matrix(3,3,""); names[1][2] = "Joe"; print(names[1][2]); // display"Joe" /** * 還能夠僅用一行代碼就建立而且使用一組初始值來初始化一個二維數組: * 對於小規模的數據, 這是建立二維數組最簡單的方式。 * */ var grades = [[89, 77, 78],[76, 82, 81],[91, 94, 89]]; print(grades[2][2]); // 顯示 89 /** * 2.處理二維數組的元素 * 兩種最基本的方式: 按行訪問和按列訪問 * */ /** * 按行訪問: * 外層循環對應行,內層循環對應列,每次對每一行的元素進行一些操做 * * 以數組 grades 爲例, 每一行對應一個學生的成績記錄。 * 能夠將該學生的全部成績相加, 而後除以科目數獲得該學生的平均成績。 * */ var grades = [[89, 77, 78],[76, 82, 81],[91, 94, 89]]; var total = 0; var average = 0.0; for (var row = 0; row < grades.length; ++row) { for (var col = 0; col < grades[row].length; ++col) { total += grades[row][col]; } average = total / grades[row].length; print("Student " + parseInt(row+1) + " average: " + average.toFixed(2)); total = 0; average = 0.0; } /** * 按列訪問: * 外層循環對應列,內層循環...,每次對每一列的元素進行一些操做 * * 下面的程序計算了一個學生各科的平均成績,即:每一列的數據想加取平均值: * */ var grades = [[89, 77, 78],[76, 82, 81],[91, 94, 89]]; var total = 0; var average = 0.0; for (var col = 0; col < grades.length; ++col) { for (var row = 0; row < grades[col].length; ++row) { total += grades[row][col]; } a verage = total / grades[col].length; print("Test " + parseInt(col+1) + " average: " + average.toFixed(2)); total = 0; average = 0.0; } /** * 3.良莠不齊的數組 * 良莠不齊的數組是指數組中每行的元素個數彼此不一樣。 有一行可能包含三個元素, 另外一行 * 可能包含五個元素, 有些行甚至只包含一個元素。 不少編程語言在處理這種良莠不齊的數 * 組時表現都不是很好, 可是 JavaScript 卻表現良好, 由於每一行的長度是能夠經過計算獲得的 * */ //假設數組 grades 中, 每一個學生成績記錄的個數是不同的, 不用修改代碼, 依然能夠正確計算出正確的平均分: var grades = [[89, 77],[76, 82, 81],[91, 94, 89, 99]]; var total = 0; var average = 0.0; for (var row = 0; row < grades.length; ++row) { for (var col = 0; col < grades[row].length; ++col) { total += grades[row][col]; } average = total / grades[row].length; print("Student " + parseInt(row+1) + " average: " + average.toFixed(2)); total = 0; average = 0.0; } /** * 4.對象數組 * 對象組成的數組,數組的方法和屬性對對象依然適用。 * */ /** * 注意 這裏經過一個函數生成了一個對象 * 生成對象的函數裏傳入參數,而後設置 * this.屬性 = ... * this.方法 = function... * 這樣的函數即構造函數 * */ function Point(x,y) { this.x = x; this.y = y; } function displayPts(arr) { for (var i = 0; i < arr.length; ++i) { print(arr[i].x + ", " + arr[i].y); } } /** * 注意 這裏經過 var ... = new 構造函數(實際參數) * 生成了該對象的一個實例對象 * */ var p1 = new Point(1,2); var p2 = new Point(3,5); var p3 = new Point(2,8); var p4 = new Point(4,4); //對象組成的數組 var points = [p1,p2,p3,p4]; for (var i = 0; i < points.length; ++i) { print("Point " + parseInt(i+1) + ": " + points[i].x + ", " + points[i].y); } var p5 = new Point(12,-3); //使用 push() 方法將點 (12, -3) 添加進數組, 使用 shift() 方法將點 (1, 2) 從數組中移除。 points.push(p5); print("After push: "); displayPts(points); points.shift(); print("After shift: "); displayPts(points); /** * 5.對象中的數組 * 在對象中, 可使用數組存儲複雜的數據。 * 實際算法應用與解決方案中, * 不少數據都被實現成一個對象, * 對象內部使用數組保存數據。 * * 下例中, 建立了一個對象, 用於保存觀測到的周最高氣溫。 * 該對象有兩個方法, 一個方法用來增長一條新的氣溫記錄, * 另一個方法用來計算存儲在對象中的平均氣溫 * * 很實用和經常使用的技巧!!! * */ //對象構造函數 function weekTemps() { this.dataStore = []; //對象構造函數裏 設置某些屬性爲一個數組存儲比較複雜的數據 this.add = add; //設置對象的方法 this.average = average; } //定義對象方法的操做,裏面使用this.屬性名 表明對象的某屬性 function add(temp) { this.dataStore.push(temp); //對對象的數組型數據進行數組式操做 } function average() { var total = 0; for (var i = 0; i < this.dataStore.length; ++i) { total += this.dataStore[i]; } return total / this.dataStore.length; } var thisWeek = new weekTemps(); thisWeek.add(52); thisWeek.add(55); thisWeek.add(61); thisWeek.add(65); thisWeek.add(55); thisWeek.add(50); thisWeek.add(52); thisWeek.add(49); print(thisWeek.average()); // 顯示 54.875
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189

四 列表-js實現

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/14. */ /** * 1.列表抽象數據類型 * 列表是一組有序的數據。 每一個列表中的數據項稱爲元素。 * 在 JavaScript 中, 列表中的元素能夠是任意數據類型。 列表中能夠保存多少元素並無事先限定,實際中受內存限制 * * 適用於: * 列表中保存的元素不是太多時。 當不須要在一個很長的序列中查找元素, 或者對其進行排序時, 列表顯得尤其有用。 * 反之, 若是數據結構很是複雜, 列表的做用就沒有那麼大了。 * * 若是存儲的順序不重要(順序重要的話能夠考慮如堆棧等), 也沒必要對數據進行查找, 那麼列表就是一種再好不過的 * 數據結構。 對於其餘一些應用, 列表就顯得太過簡陋了 * * * 屬性與方法: * listSize( 屬性) 列表的元素個數,最後一個元素的位置下標是 listSize - 1 * pos( 屬性) 列表的當前位置 * length( 屬性) 返回列表中元素的個數 * clear( 方法) 清空列表中的全部元素 * listToString( 方法) 返回列表的字符串形式,這裏不適用toString() 不去覆蓋原生的toString() * getElement( 方法) 返回當前位置的元素 * insert( 方法) 在現有元素後插入新元素 * append( 方法) 在列表的末尾添加新元素 * remove( 方法) 從列表中刪除元素 * front( 方法) 將列表的當前位置設移動到第一個元素 * end( 方法) 將列表的當前位置移動到最後一個元素 * prev( 方法) 將當前位置後移一位 * next( 方法) 將當前位置前移一位 * currPos( 方法) 返回列表的當前位置 * moveTo( 方法) 將當前位置移動到指定位置 * */ /** * 2.實現列表類,定義構造函數 * 注意這裏定義的刪除查找等方法都是傳入一整個元素的值,列表由一系列元素組成,元素即最小的那個單元 * */ function List() { this.listSize = 0; //listSize是屬性 this.pos = 0; this.dataStore = []; // 初始化一個空數組來保存列表元素,即底層數據結構是數組 this.clear = clear; this.find = find; this.listToString = listToString; this.insert = insert; this.append = append; this.remove = remove; this.front = front; this.end = end; this.prev = prev; this.next = next; this.length = length; //length是方法 this.currPos = currPos; this.moveTo = moveTo; this.getElement = getElement; this.length = length; this.contains = contains; } /** * 3. append() * 該方法給列表的下一個位置增長一個新的元素, * 這個位置恰好等於變量 listSize 的值,新元素就位後, 變量 listSize 加 1, * []訪問的時候元素個數直接就++了 * */ function append(element) { this.dataStore[this.listSize++] = element; } /** * 4. find() * find() 方法經過對數組對象 dataStore 進行迭代,查找給定的元素。 * 若是找到,就返回該元素在列表中的位置,不然返回 -1,這是在數組中找不到指定元素時返回的標準值 * */ function find(element) { for (var i = 0; i < this.dataStore.length; ++i) { if (this.dataStore[i] == element) { return i; } } return -1; } /** * 5. remove() * 須要在列表中找到該元素, 而後刪除它, 而且調整底層的數組對象以填補刪除該元素後留下的空白。 * js中可使用 splice() 方法簡化這一過程。 * * remove() 方法使用 find() 方法返回的位置對數組 dataStore 進行截取。 數組改變後, 將變 * 量 listSize 的值減 1, 以反映列表的最新長度。 若是元素刪除成功, 該方法返回 true, * 不然返回 false。 * */ function remove(element) { var foundAt = this.find(element); if (foundAt > -1) { this.dataStore.splice(foundAt, 1); --this.listSize; return true; } return false; } /** * 6. length() * 返回列表中元素的個數 * */ function length() { return this.listSize; } /** * 7. listToString() 顯示列表中的元素, * 該方法返回的是一個數組, 而不是一個字符串, 但它的目的是爲了顯示列表的 * 當前狀態, 所以返回一個數組就足夠了。 * */ function listToString() { return this.dataStore; } /** * 8. insert() 向列表中插入一個元素 * insert() 方法須要知道將元素插入到什麼位置, * 假設插入是指插入到列表中某個元素以後. * * insert() 方法用到了 find() 方法, find() 方法會尋找傳入的 after 參數在列 * 表中的位置, 找到該位置後, 使用 splice() 方法將新元素插入該位置以後, 而後將變量 * listSize 加 1 並返回 true, 代表插入成功。 * */ 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; } /** * 9. clear() 清空列表中全部的元素 * clear() 方法使用 delete 操做符刪除數組 dataStore, 接着在下一行建立一個空數組。 最 * 後一行將 listSize 和 pos 的值設爲 1, 代表這是一個新的空列表 * */ function clear() { delete this.dataStore; this.dataStore = []; this.listSize = this.pos = 0; } /** * 10. contains() 判斷給定值是否在列表中 * */ function contains(element) { for (var i = 0; i < this.dataStore.length; ++i) { if (this.dataStore[i] == element) { return true; } } return false; } /** * 11. 下面的方法都是經過控制當前位置 pos 和 listSize 來實現的 * */ //當前位置移動到首元素 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 - 1) { ++this.pos; } } //得到當前位置 function currPos() { return this.pos; } //當前位置移動移動到某個位置(傳入的是位置數字,從零開始) function moveTo(position) { this.pos = position; } /** * 12. getElement() 返回列表的當前元素 * */ function getElement() { return this.dataStore[this.pos]; } /** * 13. 應用1: 建立一個由姓名組成的列表,來展現怎麼使用這些方法 * */ //建立一個列表實例對象 var names = new List(); names.append("Clayton"); names.append("Raymond"); names.append("Cynthia"); names.append("Jennifer"); names.append("Bryan"); names.append("Danny"); //如今移動到列表中的第一個元素而且顯示它: names.front(); print(names.getElement()); // 顯示 Clayton //接下來向後移動一個單位而且顯示它: names.next(); print(names.getElement()); // 顯示 Raymond //先向前移動兩次, 而後向後移動一次, 顯示出當前元素, 看看 prev() 方法的應用 names.next(); names.next(); names.prev(); print(names.getElement()); // 顯示 Cynthia /** * !遍歷! * 由前向後遍歷列表: * 在 for 循環的一開始, 將列表的當前位置設置爲第一個元素。 只要 currPos 的值小於列表 * 的長度-1 (由於pos是從0開始的,比較完以後纔會移動next() ), 就一直循環, 每一次循環都調用 next() 方法將當前位置向前移動一位。 * */ //這裏用names.pos++比較好,由於next() pos永遠到不了names.length(),會一直循環 for (names.front(); names.currPos() < names.length(); names.pos++) { print(names.getElement()); //print(names.currPos()); } //但注意通過上面的遍歷操做,pos指向的是最後一位+1,因此要 -1一次 names.pos -= 1; /** * 從後向前遍歷列表 * 循環從列表的最後一個元素開始, 噹噹前位置大於或等於 0 時, 調用 prev() 方法後移一位。 * * 迭代器只是用來在列表上隨意移動, 而不該該和任何爲列表增長或刪除元素的方法一塊兒使用 * */ //這裏用names.pos--比較好,由於pre() pos永遠到0就不會降了,會一直循環 for(names.end(); names.currPos() >= 0; names.pos--) { print(names.getElement()); } //但注意通過上面的遍歷操做,pos指向的是-1,因此要 +1一次 names.pos += 1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259

五 棧-js實現

入棧push-出棧pop-訪問棧頂元素peek-清空棧clear

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/14. */ /** * 1.棧是一種高效的數據結構, 由於數據只能在棧頂添加或刪除, 因此這樣的操做很快 * 棧是一種特殊的列表, 棧內的元素只能經過列表的一端訪問, 這一端稱爲棧頂。 * 一摞盤子是現實世界中常見的棧的例子. * 棧具備後入先出的特色, 因此任何不在棧頂的元素都沒法訪問。 * 爲了獲得棧底的元素, 必須先拿掉上面的元素。 * * 屬性: * top 棧數組的第一個空位置 = 棧頂元素的位置+1 ,top處是空的,它處於棧頂元素之上 (top從0開始,0表明在棧底,及棧是空的),同時也爲了標記哪裏能夠加入新元素,當向棧內壓入元素時, 該變量增大 * 即:第 棧頂元素的 數組下標是 top - 1 * empty 棧內是否含有元素,用 length 屬性也能夠達到一樣的目的 * * 方法: * push() 元素入棧, * pop() 元素出棧,(也能夠訪問棧頂的元素,可是調用該方法後,棧頂元素被刪除) * peek() 預覽棧頂元素,只返回棧頂元素,不刪除它。 * length() 返回棧內元素的個數(top應該是等於數組的length的,因此用top屬性也可) * clear() 清除棧內全部元素 * */ //棧類的構造函數 function Stack() { this.dataStore = []; //底層數據結構是數組 this.top = 0; //top應該是等於數組的length的 this.push = push; this.pop = pop; this.peek = peek; this.length = length; this.clear = clear; } /** * 2. push() * 向棧中壓入一個新元素, 須要將其保存在數組中變量 top 所對 * 應的位置, 而後將 top 值加 1, 讓top指向數組中下一個空位置 * 特別注意 ++ 操做符的位置, 它放在 this.top 的後面, 這樣新入棧的元素就被放在 * top 的當前值對應的位置, 而後再將變量 top 的值加 1, 指向下一個位置 * */ function push(element) { this.dataStore[this.top++] = element; } /** * 3. pop() * pop() 方法剛好與 push() 方法相反——它返回棧頂元素, 同時將變量 top 的值減 1 * 也能夠改造一下,只--this.top,不返回棧頂元素 * */ function pop() { return this.dataStore[--this.top]; } /** * 4. peek() * peek() 方法返回數組的第 top-1 個位置的元素, 即棧頂元素 * */ function peek() { return this.dataStore[this.top-1]; } function length(){ return this.top; } function clear() { this.top = 0; } /** * 5.測試 Stack 類的實現 * */ var s = new Stack(); s.push("David"); s.push("Raymond"); s.push("Bryan"); print("length: " + s.length()); print(s.peek()); var popped = s.pop(); print("The popped element is: " + popped); print(s.peek()); s.push("Cynthia"); print(s.peek()); s.clear(); print("length: " + s.length()); print(s.peek()); s.push("Clayton"); print(s.peek()); /** * 6.棧的應用一:數字進制間的相互轉換 * * 利用棧將一個數字從一種數制轉換成另外一種數制。 * 假設想將數字 n 轉換爲以 b 爲基數 * 的數字, 實現轉換的算法以下: * (1) 最高位爲 n % b, 將此位壓入棧。 * (2) 使用 n/b 代替 n。 * (3) 重複步驟 1 和 2, 直到 n 等於 0, 且沒有餘數。 * (4) 持續將棧內元素彈出, 直到棧爲空, 依次將這些元素排列, 就獲得轉換後數字的字符 * 串形式。 * * 下面就是該函數的定義, 能夠將十進制的數字轉化爲二至九進制的數字: * */ function mulBase(num, base) { var s = new Stack(); do { s.push(num % base); num = Math.floor(num /= base); } while (num > 0); var converted = ""; while (s.length() > 0) { converted += s.pop(); } return converted; } //將數字轉換爲二進制和八進制 function mulBase(num, base) { var s = new Stack(); do { s.push(num % base); num = Math.floor(num /= base); } while (num > 0); var converted = ""; while (s.length() > 0) { converted += s.pop(); } return converted; } var num = 32; var base = 2; var newNum = mulBase(num, base); print(num + " converted to base " + base + " is " + newNum); num = 125; base = 8; var newNum = mulBase(num, base); print(num + " converted to base " + base + " is " + newNum); //輸出: 32 converted to base 2 is 100000 125 converted to base 8 is 175 // ToDo: 而二進制轉10進制和16進制怎麼轉? /** * 7.棧的應用二: 迴文 * 使用棧,能夠輕鬆判斷一個字符串是不是迴文。 將拿到的字符串的每一個字符按從左至 * 右的順序壓入棧。 當字符串中的字符都入棧後, 棧內就保存了一個反轉後的字符串, 最後 * 的字符在棧頂, 第一個字符在棧底. * * 字符串完整壓入棧內後, 經過持續彈出棧中的每一個字母就能夠獲得一個新字符串, 該字符 * 串恰好與原來的字符串順序相反。 咱們只須要比較這兩個字符串便可, 若是它們相等, 就 * 是一個迴文。 * */ //下例是一個利用前面定義的 Stack 類, 判斷給定字符串是不是迴文的程序。 function isPalindrome(word) { var s = new Stack(); for (var i = 0; i < word.length; ++i) { s.push(word[i]); } var rword = ""; while (s.length() > 0) { rword += s.pop(); } if (word == rword) { return true; } else { return false; } } var word = "hello"; if (isPalindrome(word)) { print(word + " is a palindrome."); } else { print(word + " is not a palindrome."); } word = "racecar" if (isPalindrome(word)) { print(word + " is a palindrome."); } else { print(word + " is not a palindrome."); } /** * 8.遞歸與使用棧模擬遞歸過程 * 棧經常被用來實現編程語言, 使用棧實現遞歸即爲一例 * */ //斐波那契遞歸 function factorial(n) { if (n === 0) { return 1; } else { return n * factorial(n-1); } } print(factorial(5)); //使用棧模擬上面的遞歸 function fact(n) { var s = new Stack(); while (n > 1) { s.push(n--); } var product = 1; while (s.length() > 0) { product *= s.pop(); } return product; } print(fact(5));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212

六 隊列-js實現

enqueue向隊尾添加一個元素-dequeue刪除隊首元素-front讀取隊首元素-back讀取隊尾元素queueToString顯示隊列內的全部元素-empty判斷隊列是否爲空

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/14. */ /** * 1. 隊列 * 隊列是一種列表,只能在隊尾插入元素,在隊首刪除元素。 * 隊列用於存儲按順序排列的數據, 先進先出, 先進隊列的元素優先處理。 * 能夠將隊列想象成在銀行前排隊的人羣. * 隊列被用在不少地方, 好比: * 提交操做系統執行的一系列進程、 打印任務池等, 一些仿真系統用隊列來模擬銀行或雜貨 * 店裏排隊的顧客。 * * 屬性: * 沒有自定義屬性,直接使用的是數組的一些屬性,如:length * * 方法: * enqueue() 向隊尾添加一個元素 * dequeue() 刪除隊首元素 * front() 讀取隊首元素 * back() 讀取隊尾元素 * queueToString() 方法顯示隊列內的全部元素 * empty() 判斷隊列是否爲空 * * */ //隊列類的構造函數 function Queue() { this.dataStore = []; //使用數組做爲底層數據對象 this.enqueue = enqueue; this.dequeue = dequeue; this.front = front; this.back = back; this.queueToString = queueToString; this.empty = empty; } /** * 2. enqueue(element) 向隊尾添加一個元素,藉助push * */ function enqueue(element) { this.dataStore.push(element); } /** * 3. dequeue() 刪除隊首的元素,藉助shift * */ function dequeue() { return this.dataStore.shift(); } /** * 4. front() 讀取隊首元素 * */ function front() { return this.dataStore[0]; } /** * 5. back() 讀取隊尾元素 * */ function back() { return this.dataStore[this.dataStore.length-1]; } /** * 6. queueToString() 方法顯示隊列內的全部元素: * */ function queueToString() { var retStr = ""; for (var i = 0; i < this.dataStore.length; ++i) { retStr += this.dataStore[i] + "\n"; } return retStr; } /** * 7. empty() 判斷隊列是否爲空 * */ function empty() { if (this.dataStore.length == 0) { return true; } else { return false; } } // 測試程序 var q = new Queue(); q.enqueue("Meredith"); q.enqueue("Cynthia"); q.enqueue("Jennifer"); print(q.queueToString()); q.dequeue(); print(q.queueToString()); print("Front of queue: " + q.front()); print("Back of queue: " + q.back());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

七 雙向鏈表-js實現

比單向鏈表功能更強一些-find查找節點值-insert插入節點-remove刪除節點-display打印全部節點-findLast找鏈表最後一個節點-dispReverse反序顯示雙向鏈表中全部元素

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/16. */ /** * 1. * 雙向鏈表: * * 新增: * 給 Node 對象增長一個屬性: * previous * * 從後向前遍歷則就容易多了 * 此時向鏈表插入一個節點須要更多的工做, 須要指出該節點正確的前驅和後繼。 * 可是在從鏈表中刪除節點時, 效率提升了,不須要再查找待刪除節點的前驅節點 * * 比單向鏈表新增方法: * findLast() 找出了鏈表中的最後一個節點 * dispReverse() 反序顯示雙向鏈表中的元素 * * 原有: * find() 在列表中查找給定的值; * insert() 插入刪除節點; * findPrevious() 尋找待刪除節點的前一個節點 * remove() * display() * * 屬性: * 使用一個 Node 對象來保存該鏈表的頭節點 * 頭結點是一直不包含數據的,它只起指向下一個節點的做用 * * !! 通常建議使用雙向鏈表,功能性更強 !! * */ /* Todo 待本身實現方法: * advance(n) 方法, 使當前節點向前移動 n 個節點。 * back(n) 方法, 使當前節點向後移動 n 個節點。 * show() 方法, 只顯示當前節點上的數據。 */ /** * 2. * 爲單向鏈表的 Node 類增長一個 previous 屬性 * */ function Node(element) { this.element = element; this.next = null; this.previous = null; } function LList() { this.head = new Node("head"); this.find = find; this.insert = insert; this.display = display; this.remove = remove; this.findLast = findLast; this.dispReverse = dispReverse; } /** * 3.雙向鏈表的 insert() 方法和單向鏈表的相似, * 可是須要設置新節點的 previous 屬性, 使其指向該節點的前驅節點 * */ function insert(newElement, item) { var newNode = new Node(newElement); var current = this.find(item); newNode.next = current.next; newNode.previous = current; current.next = newNode; } /** * 4.雙向鏈表的 remove() 方法比單向鏈表的效率更高 * 首先須要在鏈表中找出存儲待刪除數據的節點, 而後設置該節點前驅的 next 屬性, 使其指向待刪 * 除節點的後繼; 設置該節點後繼的 previous 屬性, 使其指向待刪除節點的前驅 * */ function remove(item) { var currNode = this.find(item); if (!(currNode.next == null)) { currNode.previous.next = currNode.next; currNode.next.previous = currNode.previous; currNode.next = null; currNode.previous = null; } } /** * 5. findLast() * 爲了完成以反序顯示鏈表中元素這類任務, 須要給雙向鏈表增長一個工具方法, 用來查找 * 最後的節點。 findLast() 方法找出了鏈表中的最後一個節點, 同時免除了從前日後遍歷鏈 * 表之苦 * */ function findLast() { var currNode = this.head; while (!(currNode.next == null)) { currNode = currNode.next; } return currNode; } /** * 6. dispReverse() 反序顯示雙向鏈表中的元素 * */ function dispReverse() { var currNode = this.head; currNode = this.findLast(); while (!(currNode.previous == null)) { print(currNode.element); currNode = currNode.previous; } } /** * 7.原來的display(),find(),insert()進行相應的修改 * */ function display() { var currNode = this.head; while (!(currNode.next == null)) { print(currNode.next.element); currNode = currNode.next; } } function find(item) { var currNode = this.head; while (currNode.element != item) { currNode = currNode.next; } return currNode; } function insert(newElement, item) { var newNode = new Node(newElement); var current = this.find(item); newNode.next = current.next; newNode.previous = current; current.next = newNode; } /** * 8. 測試一 * */ var cities = new LList(); cities.insert("Conway", "head"); cities.insert("Russellville", "Conway"); cities.insert("Carlisle", "Russellville"); cities.insert("Alma", "Carlisle"); cities.display(); print(); cities.remove("Carlisle"); cities.display(); print(); cities.dispReverse(); /* 輸出: Conway Russellville Carlisle Alma Conway Russellville Alma Alma Russellville Conway * */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167

八 字典-js實現

按鍵值對進行存儲查詢-add新增鍵值對-find以鍵做爲參數返值-remove刪一個鍵值對-showAll顯示全部鍵值對-count獲得元素個數-clear清空全部鍵值對-showAllBySortKey按鍵排序後顯示全部鍵值對

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/16. */ /** * 1.字典 * 一種以鍵 - 值對形式存儲數據的數據結構, * 鍵是指你用來查找的東西, 值是查找獲得的結果 * * 適用: * 電話本,!!按鍵值對進行存儲查詢的結構!!,由於C++中沒有固定的按鍵值對查詢的結構(js有對象), * 因此遇到這種狀況要用 字典結構, * 再如:存儲一段文本中各個單詞出現的次數。該程序顯示每一個單詞出現的次數, * 但每一個單詞只顯示一次(只顯示一次能夠用做字典,由於字典裏的鍵也是不能重複出現的) * * add 新增一個鍵值對 * find 以鍵做爲參數, 返回和其關聯的值 * remove 刪除一個鍵 - 值對 * showAll 顯示字典中全部的鍵 - 值對 * count 獲得字典中的元素個數 * clear 清空全部鍵值對 * showAllBySortKey 按鍵排序後顯示字典全部鍵值對的 * */ function Dictionary() { this.add = add; /*2.適用數組做爲基礎數據類型,本質也是對象*/ this.datastore = new Array(); this.find = find; this.remove = remove; this.showAll = showAll; this.count = count; this.clear = clear; this.showAllBySortKey = showAllBySortKey; } /** * 3. add(key,value) * 新增一個鍵值對 * 接受兩個參數: 鍵和值。 鍵是值在字典中的索引。 * */ function add(key, value) { this.datastore[key] = value; } /** * 4. find(key) * 以鍵做爲參數, 返回和其關聯的值 * */ function find(key) { return this.datastore[key]; } /** * 5. remove(key) * 刪除一個鍵 - 值對,須要使用 JavaScript 中的一個內置函數: delete。 該函數是 Object * 類的一部分, 使用對鍵的引用做爲參數。 該函數同時刪掉鍵和與其關聯的值 * */ function remove(key) { delete this.datastore[key]; } /** * 6. showAll() * 顯示字典中全部的鍵 - 值對 * */ function showAll() { /** * 7. 能夠調用 Object 類的 keys() 方法返回傳入參數中存儲的全部鍵組成的數組, * 這裏不須要, * * 由於for in 循環 的: * for(var i in 數組/對象){...} * i 直接就是 數組下標 或者 對象的屬性名(及字典的鍵名) * */ for(var key in this.datastore) { print(key + " -> " + this.datastore[key]); } } /** * 7. * count * 獲得字典中的元素個數 * * !不能使用 length 屬性, 由於當鍵的類型爲字符串時, length 屬性就無論用了! * */ function count() { var n = 0; for(var key in Object.keys(this.datastore)) { ++n; } return n; } /** * 8. clear() * 清空全部鍵值對 * 定義以下: * */ function clear() { for (var key in Object.keys(this.datastore)) { delete this.datastore[key]; } } /** * 9. 字典的主要用途是經過鍵取值, 咱們無須太關心數據在字典中的實際存儲順序。 然而, 很 * 多人都但願看到一個有序的字典. * * 下面是 按鍵排序後顯示字典全部鍵值對的 * showAllBySortKey() * * 這裏排序的時候,i就是 1234 , 由於 in 後邊是 鍵組成的數組 * */ function showAllBySortKey() { for(var i in Object.keys(this.datastore).sort()) { //print(Object.keys(this.datastore).sort()) //從排序過的經過i獲得排序序列對應的key值 var key = Object.keys(this.datastore).sort()[i]; print(key + " -> " + this.datastore[key]); } } //使用 Dictionary 類 //load("Dictionary.js"); var pbook = new Dictionary(); pbook.add("Mike","123"); pbook.add("David", "345"); pbook.add("Cynthia", "456"); print("David's extension: " + pbook.find("David")); //pbook.remove("David"); //print("Number of entries: " + pbook.count()); pbook.showAll(); pbook.showAllBySortKey(); pbook.clear(); print("Number of entries: " + pbook.count()); pbook.showAll();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138

九 散列-js實現

散列表HashTable-插入刪除和取用數據很是快-查找特定值效率低.js

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/16. */ /** * 1. * 散列 * 散列是一種經常使用的數據存儲技術,散列使用的數據結構叫作散列表。 * 在散列表上插入、 刪除和取用數據都很是快, * 可是對於查找操做來講卻效率低下, 好比查找最大最小值。 得求助於其餘數據結構, 二叉查找樹是一個很好的選擇 * * 散列表 * 散列表是基於數組進行設計的 * 使用散列表存儲數據時, 經過一個 散列函數 將 鍵映射爲一個數字(做爲惟一的數組索引), * 這個數字的範圍是 0 到散列表的長度 * * 即便用一個高效的散列函數, 仍然存在將兩個鍵映射成同一個值的可能, 這稱爲碰撞 * * 散列表中的數組大小常見的限制是: 數組長度應該是一個質數 * */ /** * 2. * * */ function HashTable() { this.table = new Array(137); this.simpleHash = simpleHash; this.betterHash = betterHash; this.showDistro = showDistro; this.put = put; //this.get = get; } /** * 3. * */ function put(data) { /** 6. * put() 方法如今使用了新的散列函數 betterHash(), 而不是原來的 simpleHash()。 * */ //var pos = this.simpleHash(data); var pos = this.betterHash(data); this.table[pos] = data; } /** 4. * 使用ASCII 碼值想加做爲鍵的散列函數,容易產生碰撞 * */ function simpleHash(data) { var total = 0; for (var i = 0; i < data.length; ++i) { total += data.charCodeAt(i); } return total % this.table.length; } /**5. * 使用霍納算法優化的散列函數 * 仍然先計算字符串中各字符的 ASCII 碼值, 不過求和時每次要乘以一個質數。 * 大多數算法書建議使用一個較小的質數, 好比 31, 可是對於咱們的數據集, 31 不起做用, * 咱們使用 37, 這樣恰好不會產生碰撞 * */ function betterHash(string) { const H = 37; var total = 0; for (var i = 0; i < string.length; ++i) { total += H * total + string.charCodeAt(i); } total = total % this.table.length; if (total < 0) { total += this.table.length-1; } return parseInt(total); } function showDistro() { var n = 0; for (var i = 0; i < this.table.length; ++i) { if (this.table[i] != undefined) { print(i + ": " + this.table[i]); } } } //測試 var someNames = ["David", "Jennifer", "Donnie", "Raymond", "Cynthia", "Mike", "Clayton", "Danny", "Jonathan"]; var hTable = new HashTable(); for (var i = 0; i < someNames.length; ++i) { hTable.put(someNames[i]); } hTable.showDistro();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

十 樹-js實現

樹-二叉查找樹BST實現-insert插入新節點-inOrder中序遍歷-preOrder先序遍歷-postOrder後序遍歷-getMin查找最小值-getMax查找最大值-find查找給定值

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/17. */ /** * 1.樹 * 樹是一種非線性的數據結構, 以分層的方式存儲數據。 * * 適用於: * 樹被用來存儲具備層級關係的數據, 好比文件系統中的文件; * 樹還被用來存儲有序列表。 * 公司組織結構圖 * * 優點: * 選擇樹而不是那些基本的數據結構, 是由於: * 二叉樹上進行查找很是快( 鏈表上查找較慢), * 二叉樹添加或刪除元素也很是快( 數組執行添加或刪除較慢) * * 基本概念: * 樹由一組以邊鏈接的節點組成 * 葉子節點:沒有任何子節點的節點 * 從一個節點到另外一個節點的這一組 邊 稱爲路徑 * 樹能夠分爲幾個層次, 根節點是第 0 層, 它的子節點是第 1 層,樹的層數就是樹的深度 * 樹的遍歷:以某種特定順序訪問樹中 全部的節點 * 每一個節點都有一個與之相關的值, 該值有時被稱爲鍵,(同時每一個節點還能夠保存數據) * */ /** * 2.二叉樹 * 二叉樹是一種特殊的樹, 它的子節點個數不超過兩個 * */ /** * 3.實現二叉查找樹(BST) * */ /** * 4.先定義節點類 * Node 對象既保存數據, 也保存和其餘節點的連接( left 和 right) * show() 顯示保存在節點中的數據 * node.left 和 node.right分別對應着左子和右子節點,插入函數中會根據它們的值將節點插入到合適的位置 * */ function Node(data, left, right) { this.data = data; this.left = left; this.right = right; this.show = show; } function show() { return this.data; } /** * 5.定義二叉查找樹( BST)類 * insert * * */ function BST() { /*初始化根節點爲null*/ this.root = null; this.insert = insert; this.inOrder = inOrder; this.preOrder = preOrder; this.postOrder = postOrder; this.getMax = getMax; this.getMin = getMin; this.find = find; } /** * 向樹中加入新節點。 * 首先建立一個 Node 對象, 將數據傳入該對象保存。 * * 其次檢查 BST 是否有根節點, * 若是沒有, 那是新樹, 該節點就是根節點,到此完成了; * 若是待插入節點不是根節點, 那就要遍歷 BST, 找到插入的適當位置。 * 該過程相似於遍歷鏈表: * 用一個變量存儲當前節點, 一層層地遍歷 BST。 * 進入 BST 之後,找到正確的節點插入點, 再跳出循環。 * * 查找正確插入點的算法以下。 * (1) 設根節點爲當前節點。 * (2) 若是待插入節點保存的數據小於當前節點, 則設新的當前節點爲原節點的左節點; 反之, 執行第 4 步。 * (3) 若是當前節點的左節點爲 null, 就將新的節點插入這個位置, 退出循環; 反之, 繼續執行下一次循環。 * (4) 設新的當前節點爲原節點的右節點。 * (5) 若是當前節點的右節點爲 null, 就將新的節點插入這個位置, 退出循環; 反之, 繼續執行下一次循環。 * */ function insert(data) { var n = new Node(data, null, null); if (this.root == null) { this.root = n; } else { var current = this.root; var parent; while (true) { parent = current; if (data < current.data) { current = current.left; if (current == null) { parent.left = n; break; } } else { current = current.right; if (current == null) { parent.right = n; break; } } } } } /** * 遍歷 * 有三種遍歷 BST 的方式: 中序、 先序和後序。 * 中序遍歷按照節點上的鍵值, 以 升序訪問 BST 上的全部節點。 * 先序遍歷 先訪問根節點 , 而後以一樣方式訪問左子樹和右子樹。 * 後序遍歷先訪問葉子節點, 從左子樹到右子樹, 再到根節點。 * * 三個遍歷都接受一個參數,是當前要遍歷樹或子樹的根節點 * * inOrder() 和 preOrder() 方法的惟一區別, 就是 if 語句中代碼的順序。 在 inOrder() * 方法中, show() 函數像三明治同樣夾在兩個遞歸調用之間; 在 preOrder() 方法中, show() * 函數放在兩個遞歸調用以前。 * */ function inOrder(node) { if (!(node == null)) { inOrder(node.left); putstr(node.show() + " "); inOrder(node.right); } } function preOrder(node) { if (!(node == null)) { putstr(node.show() + " "); preOrder(node.left); preOrder(node.right); } } function postOrder(node) { if (!(node == null)) { postOrder(node.left); postOrder(node.right); putstr(node.show() + " "); } } /*測試插入節點和三種遍歷二叉樹的方式*/ var nums = new BST(); nums.insert(23); nums.insert(45); nums.insert(16); nums.insert(37); nums.insert(3); nums.insert(99); nums.insert(22); print("Inorder traversal: "); inOrder(nums.root); print("Preorder traversal: "); preOrder(nums.root); print("Postorder traversal: "); postOrder(nums.root); /** * 查找: * BST 一般有三種類型的查找: * * 查找最小值: * 沿着 BST 的左子樹挨個遍歷, 直到遍歷到 BST 最左邊的節點即爲最小值 * * 查找最大值: * 遍歷右子樹, 直到找到最後一個節點, 該節點上保存的值即爲最大值 * * 查找給定值: * 比較該值和當前節點上的值的大小。經過比較,肯定若是給定值不在當前節點,該向左遍歷仍是向右遍歷 * 若是找到給定值, 該方法返回保存該值的節點; 若是沒找到, 該方法返回 null * */ function getMin() { var current = this.root; while (!(current.left == null)) { current = current.left; } return current.data; } function getMax() { var current = this.root; while (!(current.right == null)) { current = current.right; } return current.data; } function find(data) { var current = this.root; while (current != null) { if (current.data == data) { return current; } else if (data < current.data) { current = current.left; } else { current = current.right; } } return null; } //測試 查找最小值 最大值 特定值 var nums = new BST(); nums.insert(23); nums.insert(45); nums.insert(16); nums.insert(37); nums.insert(3); nums.insert(99); nums.insert(22); inOrder(nums.root); print("\n"); putstr("Enter a value to search for: "); var value = parseInt(readline()); // 查找方式: 樹.find(節點值) var found = nums.find(value); if (found != null) { print("Found " + value + " in the BST."); } else { print(value + " was not found in the BST."); } /** * 刪除節點, * 使用remove(data) 它會調用removeNode() * 會從根節點開始查起 * */ function remove(data) { root = removeNode(this.root, data); } function removeNode(node, data) { if (node == null) { return null; } if (data == node.data) { // 沒有子節點的節點 if (node.left == null && node.right == null) { return null; } // 沒有左子節點的節點 if (node.left == null) { return node.right; } // 沒有右子節點的節點 if (node.right == null) { return node.left; } // 有兩個子節點的節點 var tempNode = getSmallest(node.right); node.data = tempNode.data; node.right = removeNode(node.right, tempNode.data); return node; } else if (data < node.data) { node.left = removeNode(node.left, data); return node; } else { node.right = removeNode(node.right, data); return node; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275

十一 圖-js實現

直接上代碼,總結見註釋:

/** * Created by chenhaoact on 16/8/18. */ /** * 1.圖 * 圖由邊的集合及頂點的集合組成 * * 環:由指向自身的頂點組成的路徑稱爲環, 環的長度爲 0 * 圈:至少有一條邊的路徑, 且路徑的第一個頂點和最後一個頂點相同 * 簡單圈:沒有重複邊或重複頂點的圈 * 平凡圈:除了第一個和最後一個頂點之外, 路徑的其餘頂點有重複的圈 * 頂點強相連:兩個頂點之間有路徑, 那麼這兩個頂點就是強連通 * 若是有向圖的全部的頂點都是強連通的, 那麼這個有向圖也是強連通的. * * 適用: * 對交通流量建模, 頂點能夠表示街道的十字路口, 邊能夠表示街道。 * 加權的邊能夠表示限速或者車道的數量。 判 最佳路線及最有可能堵車的街道。 * 任何運輸系統均可以用圖來建模。 * 航空公司能夠用圖來爲其飛行系統建模。 * * 包含局域網和廣域網( 如互聯網) 在內的計算機網絡, 一樣常常用圖來建模。 * * 消費市場, 頂點能夠用來表示供應商和消費者 * * 經常使用於解決的問題: * 查找最短路徑 * * */ /** * 2.Vertex 類來保存頂點和邊。 * 這個類的做用與鏈表和二叉搜索樹的 Node 類同樣。 * Vertex 類有兩個數據成員: * label:一個用於標識頂點 * wasVisited:頂點是否被訪問過的布爾值 * 將全部頂點保存到數組中, 在圖類裏, 能夠經過它們在數組中的位置引用它們 * */ function Vertex(label) { this.label = label; } /** * 3. * 構建圖類 * * 表示圖的邊的方法 * 法一:鄰接表(鄰接表數組)。 * 存儲 每一個頂點的全部相鄰頂點的列表(數組) 構成的數組, 該頂點做爲索引 * 這樣就知道了定點和哪些頂點連成邊 * * 法二:鄰接矩陣。 * 一個二維數組, 其中的元素表示兩個頂點之間是否有一條邊。 * * 下面的圖類: * 屬性: * vertices 節點數, Graph(v)傳入的v是節點數 * edges 邊數 * adj (鄰接表數組,這裏使用了法一,一個二維數組,每一個節點的臨界節點數組組成的數組) * marked 數組,存儲已訪問過的頂點 * edgeTo 一個數組,保存從一個頂點到下一個頂點的全部邊 * 方法: * addEdge(節點1,節點2) 添加一條邊 * showGraph() 打印全部頂點及其相鄰頂點列表的方式來顯示圖 * dfs(節點) 深度優先的遍歷獲得該節點全部能到達的路徑上的全部節點 * bfs(節點) 廣度優先遍歷 獲得該節點全部能到達的路徑上的全部節點 * */ function Graph(v) { this.vertices = v; this.edges = 0; this.adj = []; //經過 for 循環爲數組中的每一個元素添加一個子數組來存儲全部的相鄰頂點, 並將全部元素初始化爲空字符串 for (var i = 0; i < this.vertices; ++i) { this.adj[i] = []; this.adj[i].push(""); } this.marked = []; for (var i = 0; i < this.vertices; ++i ) { this.marked[i] = false; } this.edgeTo = []; this.addEdge = addEdge; this.showGraph = showGraph; this.dfs = dfs; this.bfs = bfs; } /** * 4. * 傳入頂點 A 和 B 時, 函數會先查找頂點 A 的鄰接表, 將頂點 B 添加到列 * 表中, 而後再查找頂點 B 的鄰接表, 將頂點 A 加入列表。 最後, 這個函數會將邊數加 1 * */ function addEdge(v, w) { this.adj[v].push(w); this.adj[w].push(v); this.edges++; } /** * 5. * 打印全部頂點及其相鄰頂點列表的方式來顯示圖 * */ 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] != undefined) putstr(this.adj[i][j] + ' '); } print(); } } //測試 g = new Graph(5); g.addEdge(0,1); g.addEdge(0,2); g.addEdge(1,3); g.addEdge(2,4); g.showGraph(); /* 0 -> 1 2 1 -> 0 3 2 -> 0 4 3 -> 1 4 -> 2 輸出顯示, 頂點 0 有到頂點 1 和頂點 2 的邊; 頂點 1 有到頂點 0 和頂點 3 的邊 * */ /** * 6. * * 深度優先搜索算法比較簡單: 訪問一個沒有訪問過的頂點, 將它標記爲已訪問, 再遞歸地 * 去訪問在初始頂點的鄰接表中其餘沒有訪問過的頂點,如此往復, 直到沒有路徑爲止。 這不是在搜 * 索特定的路徑, 而是經過搜索來查看在圖中有哪些路徑能夠選擇 * * dfs(節點): 深度優先的遍歷該節點開始全部能到達的路徑,並顯示從該節點能到達(訪問)的全部節點 * */ function dfs(v) { this.marked[v] = true; // 用於輸出的 if 語句在這裏不是必須的 if (this.adj[v] != undefined) print("Visited vertex: " + v); for (var w in this.adj[v]) { if (!this.marked[w]) { this.dfs(w); } } } //測試深度優先 dfs() g = new Graph(5); g.addEdge(0, 1); g.addEdge(0,2); g.addEdge(1,3); g.addEdge(2,4); g.showGraph(); g.dfs(0); /* 0 -> 1 2 1 -> 0 3 2 -> 0 4 3 -> 1 4 -> 2 Visited vertex: 0 Visited vertex: 1 Visited vertex: 3 Visited vertex: 2 Visited vertex: 4 從節點0開始能訪問到的節點有 0 1 2 3 4 */ //測試廣度優先 g = new Graph(5); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 3); g.addEdge(2, 4); g.showGraph(); g.bfs(0); /* 0 -> 1 2 1 -> 0 3 2 -> 0 4 3 -> 1 4 -> 2 Visited vertex: 0 Visited vertex: 1 Visited vertex: 2 Visited vertex: 3 Visited vertex: 4 * */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196

另外還有一些基本的算法像排序,檢索,動態規劃,貪心,只要知道了如何用js去實現數據結構和算法,其餘的都是共通的。建議配合這本《數據結構與算法JavaScript描述》和《算法導論》一塊兒讀,而後把《算法導論》中的重要算法所有用js實現一遍,相信對編程能力會有很大的提高。

友情連接:https://blog.csdn.net/haoshidai/article/details/52263191
相關文章
相關標籤/搜索