提到資料結構與演算法都感覺這應該是後端要掌握的知識,對前端來說只要寫寫頁面,繫結事件,向後臺發發資料就好了,用不到資料結構與演算法,也許對於一些資料查詢 簡單的for迴圈就能搞定,也許只是提高了幾毫秒而已,可忽略不計,假入node做後臺開發的時候, 一次請求節約的幾毫秒,千萬次請求節約的就不是毫秒的時間的,資料結構是作為高階程式工程師必會的知識
先來看看js資料型別
- 基本型別(棧 stack) : Number、String 、Boolean、Null 和 Undefined , Symbol(es6 新增); 基本資料型別是按值訪問 由高向低分配,棧記憶體最大是 8MB,(超出報棧溢位), String:是特殊的棧記憶體 (向高分配大小不定),程式設計師分配
- 引用型別(堆 heap) :Object 、Array 、Function 、Data;引用型別資料在棧記憶體中儲存的實際上是物件在堆記憶體中的引用地址(指標),向高分配,系統自動分配
一、堆疊空間分配區別:
- 棧(作業系統):由作業系統自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧;
- 堆(作業系統): 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由 OS 回收,分配方式倒是類似於連結串列。
二、堆疊快取方式區別:
- 棧使用的是一級快取, 他們通常都是被呼叫時處於儲存空間中,呼叫完畢立即釋放;
- 堆是存放在二級快取中,生命週期由虛擬機器的垃圾回收演算法來決定(並不是一旦成為孤兒物件就能被回收)。所以呼叫這些物件的速度要相對來得低一些。
三、堆 、棧資料結構區別:
- 堆(資料結構):堆可以被看成是一棵樹,如:堆排序;
- 棧(資料結構):一種先進後出的資料結構。
資料結構
資料結構是指相互之間存在著一種或多種關係的資料元素的集合和該集合中資料元素之間的關係組成;資料結構的基本操作的設定的最重要的準則是,實現應用程式與儲存結構的獨立(資料結構=資料的儲存+演算法)
資料結構分類
-
邏輯結構:反映資料之間的邏輯關係;
-
儲存結構:資料結構在計算機中的表示;
邏輯結構:
集合:結構中的資料元素除了同屬於一種型別外,別無其它關係。(無邏輯關係) 線性結構 :資料元素之間一對一的關係(線性表) 樹形結構 :資料元素之間一對多的關係(非線性) 圖狀結構或網狀結構: 結構中的資料元素之間存在多對多的關係(非線性) 複製程式碼
儲存結構:
順序儲存資料結構 鏈式儲存資料結構 索引儲存資料結構 雜湊儲存資料結構 複製程式碼
線性結構 :
- 佇列: 也是一種運算受限的線性表。它只允許在表的一端進行插入,而在另一端進行刪除。允許刪除的一端稱為隊頭(front),允許插入的一端稱為隊尾(rear)。先進先出。
- 棧: 是限制在表的一端進行插入和刪除運算的線性表,通常稱插入、刪除的這一端為棧頂(Top),另一端為棧底(Bottom)。先進後出。top= -1時為空棧,top=0只能說明棧中只有一個元素,並且元素進棧時top應該自增. 後進先出
- 串 :是零個或多個字元組成的有限序列。長度為零的串稱為空串(Empty String),它不包含任何字元。通常將僅由一個或多個空格組成的串稱為空白串(Blank String) 注意:空串和空白串的不同,例如“ ”和“”分別表示長度為1的空白串和長度為0的空串。
非線性結構
- 樹:一種非線性結構。樹是遞迴結構,在樹的定義中又用到了樹的概念
- 有序數:子節點之間有順序關係
- 無序樹:子節點之間沒有順序關係
- 二叉樹:一種非線性結構。樹是遞迴結構,在樹的定義中又用到了樹的概念
二叉樹遍歷
使得每一個結點均被訪問一次,而且僅被訪問一次。非遞迴的遍歷實現要利用棧。
-
先序遍歷DLR:根節點->左子樹->右子樹(廣度遍歷) 複製程式碼
-
中序遍歷LDR:左子樹->根節點->右子樹。必須要有中序遍歷才能得到一棵二叉樹的正確順序(廣度遍歷) 複製程式碼
-
後續遍歷LRD:左子樹->右子樹->根節點。需要棧的支援。(廣度遍歷) 複製程式碼
-
層次遍歷:用一維陣列儲存二叉樹時,總是以層次遍歷的順序儲存結點。層次遍歷應該藉助佇列。(深度遍歷) 複製程式碼
記憶體: 一條很長一維陣列;
演算法
演算法特徵:
有窮性、確定性、可行性、輸入、輸出
演算法設計衡量:
正確性、可讀性、健壯性, 時間複雜度, 空間複雜度
演算法分類
基本演算法(必會)
氣泡排序
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len - 1; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) { // 相鄰元素兩兩對比
var temp = arr[j+1]; // 元素交換
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
複製程式碼
快速排序
function swap(items, firstIndex, secondIndex){
var temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
}
function partition(items, left, right) {
var pivot = items[Math.floor((right + left) / 2)],
i = left,
j = right;
while (i <= j) {
while (items[i] < pivot) {
i++;
}
while (items[j] > pivot) {
j--;
}
if (i <= j) {
swap(items, i, j);
i++;
j--;
}
}
return i;
}
function quickSort(items, left, right) {
var index;
if (items.length > 1) {
index = partition(items, left, right);
if (left < index - 1) {
quickSort(items, left, index - 1);
}
if (index < right) {
quickSort(items, index, right);
}
}
return items;
}
var items = [3,8,7,2,9,4,10]
var result = quickSort(items, 0, items.length - 1);
複製程式碼
插入排序
function insertionSort(arr) {
var len = arr.length;
var preIndex, current;
for (var i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while(preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex+1] = arr[preIndex];
preIndex--;
}
arr[preIndex+1] = current;
}
return arr;
}
複製程式碼
選擇排序
function selectionSort(arr) {
var len = arr.length;
var minIndex, temp;
for (var i = 0; i < len - 1; i++) {
minIndex = i;
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { // 尋找最小的數
minIndex = j; // 將最小數的索引儲存
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
複製程式碼
時間空間複雜度
- 在氣泡排序,插入排序,選擇排序,快速排序中,在最最壞情況下,快速排序的時間複雜為O(n2) ,插入排序O(n2),選擇排序O(n2),氣泡排序O(n2)