序文
他のITの仕事に比べてフロントポストの要件は、アルゴリズムはまだ比較的低いです。しかし、私は白の学校の募集の面接テンセント、アリババ、百度や他のメーカーを経験している、基本的なアイデアやアルゴリズムが習得しなければならないことがわかりました。そこで、近年では、ゆっくりと私は基本的なアルゴリズムを勉強し始めたとフロントエンド「で説明したJavaScriptのデータ構造とアルゴリズムは、」読書のために特に適していることがわかりました。
次に、我々は10件のアイデアやアルゴリズムの使用シナリオは、多くの場合、次の面接をテストし分析します。
まず、バブルソート(バブルソート)
バブルソート順序交換を注文する最も簡単な方法であり、主なアイデアは、次のとおりです。交換は順序が逆ならば、これまでのシリーズの全く逆の順序がなくなるまでのシーケンスは、ソートするレコードに隣接する二つの数字を選択します。
1、アルゴリズム記述
- 隣接する要素の比較。最初は、それらの両者を交換するために、第二よりも大きい場合。
- 私たちは、最初から最後のペアの最初の終わりには、隣接する要素のペアごとに同じ作業を行い、そのためには、最後の要素は、最大数であるべきです。
- 最後の1を除いて、すべての要素について、上記の手順を繰り返します。
- ソートが完了するまで3に、手順1を繰り返します。
図2に示すように、コードの実装
function bubbleSort(arr) {
var len = arr.length;
for(var i = 0;i < len;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;
}
复制代码
第二に、クイックソート(クイックソート)
クイックソート、バブルソートは、改善の一種です。クイックソートでは、レコード及び移動が中央に両端から行われる比較し、大きい値が一旦前面から背面に移動させる記録することができ、小さな値は一度こうして全体を減少させる、前方に戻ってから移動を記録することができます比較の数、および携帯電話番号。
1、アルゴリズム記述
次のように分割を使用してクイックソートおよび列2(サブリスト)の数に列番号(リスト)を征服、特定のアルゴリズムです。
- シリーズからの1つの要素を選択、「基準」(ピボット)と呼ばれます。
- 列を並べ替え、基準値よりも小さいベースの前方に配置されているすべての要素は、すべての要素が基準値よりも大きいベースラインの背後に配置され(同じ番号はどちら側でもよいです)。パーティション終了後、中間位置の列の数に基づいて。これは、パーティション(パーティション)動作と呼ばれます。
- 再帰的に(これを再帰的)基準値よりも小の数が列の数とサブエレメントは、エレメント列の基準値よりも大きいです。
図2に示すように、コードの実装
function quickSort(arr, left, right) {
var len = arr.length,
partitionIndex,
left = typeof left != 'number'? 0 : left,
right = typeof right != 'number'? len -1 : right;
if(left < right) {
partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex-1);
quickSort(arr, partitionIndex+1, right);
}
}
// 分区操作
function partition(arr, left, right) {
// 设定基准值pivot
var pivot = left,
index = pivot+1;
for(var i = index;i<= right;i++){
if(arr[i] < arr[pivot]){
swap(arr, i, index);
index++;
}
}
swap(arr, pivot, index-1);
return index-1;
}
// 交换数据
function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
复制代码
第三に、挿入ソート(挿入ソート)
挿入ソートは、「挿入」並べ替え方法のクラスである、主なアイデアは、次のとおりです。番号は、そのサイズのキーが正しく順序付けられたシーケンスに配置された挿入されているに応じてソートされるたびに、数字のすべての行まで良いため。
1、アルゴリズム記述
次のように説明した特定のアルゴリズムを達成するために、配列にインプレース使用してシーケンシングを挿入します。
- ソートされていると考えることができ、最初の要素で始まります。
- 前方スキャンから次の要素を削除する要素の順序でソートされています。
- 要素(ソート)は、新しい要素、次の位置への要素よりも大きい場合。
- ステップ3を繰り返し、それは以下の要素の新しい位置に等しいソート要素を見つけるまで。
- 新しい要素は、この位置に挿入された後。
- ステップ2〜5を繰り返します。
図2に示すように、コードの実装
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;
}
复制代码
第四に、ヒルはソート(シェルソート)
シェルソートサブシーケンスの数に分類される最初のシーケンス全体、実質的に全体のシーケンスを順序付けする、配列の直接挿入ソートで行われ、次いで、:、挿入ソート、ソートの基本的な考え方である改善され挿入ソート、一度全体の配列。
1、アルゴリズム記述
- 増分シーケンスT1、T2、...、TK、TI> TJ、TK = 1を選択します。
- シーケンス番号k、k回配列がソートされインクリメント。
- 対応するインクリメントTIに応じて片道ソート、列がそれぞれ直接挿入ソートのために各サブテーブルの長さmのいくつかのサブシーケンスに分類することができます。唯一のデルタ係数は処理テーブルとして、シーケンス全体が1であり、テーブルの長さは、シーケンス全体の長さです。
図2に示すように、コードの実装
function SellSort(arr) {
var len = arr.length;
for(var gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
// 多个分组交替执行
for(var i = gap; i < len;i++) {
var j = i;
var current = arr[i];
while (j - gap >= 0 && current < arr[j - gap]) {
arr[j] = arr[j - gap];
j = j - gap;
}
arr[j] = current;
}
}
return arr;
}
复制代码
第五に、選択ソート(選択ソート)
選択ソート、その後まず、最小値が列をソートするために選択され、照合順序に記憶された位置を開始し、残りのソートされていない要素から最小の要素を探し続け、PUT:、シンプルで直感的なソートアルゴリズムで、基本的な考え方がありますソートされたシーケンスの終わりまで。ように、すべての要素がソートされるまで。
1、アルゴリズム記述
ダイレクト選択ソートNレコードは、直接選択整然としたソート結果を介してN-1回であってもよいです。アルゴリズムは次のように説明されています。
- 初期状態:領域乱れが空である領域を命じ、R [1..nの]です。
- I(I = 1,2,3 ... N-1)開始を注文実行、現在の順序付けられた領域と不規則領域はR [1..i-1]およびR(i..n)でした。現在のソート無秩序ゾーンから旅行 - R [1..i]とR [I + 1となるようR [K]選択された最小記録鍵は、それは、最初のレコード無秩序領域Rと交換します..n)レコードの数とレコード疾患の新たな面積を削減する新しい注文の数を増加させるために変更されました。
- N-1旅の終わり、規則的な配列。
図2に示すように、コードの実装
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;
}
复制代码
第六に、ヒープの並べ替え(ソートヒープ)
ヒープソート、ヒープソートアルゴリズムは、データ構造の設計を使用しています。各ノードの値は、以下(小スタックと呼ばれるルート)、左右の子ノードの値と同じであるか、または各ノードの値は、左と右の子ノード以上である:ヒープは、以下の特性を有する完全二分木であります値(のような大きなヒープルートと呼びます)。
1、アルゴリズム記述
- ソートする最初のキー列(R1、R2 ... .Rn)は、初期不規則領域のスタックスタックの最上部よりも大きくなるように構成されました。
- 元素Rのスタックの最上位[1]およびR [N-】交換、この新しい無秩序領域(R1、R2、... RN-1)と新しい順序付き領域(のRnの)を得るための時間、及び満足Rの最後の要素[1,2 ... N-1] <= R [N]。
- スタックの性質に違反している可能性[1] Rの交換後のスタックの新しいトップので、新たなスタックに調整される現在の無秩序領域(R1、R2、... RN-1)のために必要であり、再度R [1]と無秩序新しい無秩序領域(R1、R2 ... .Rn-2)及び新しい順序付き領域(RN-1、RN)の最後の要素の面積結果を交換します。N-1の領域を順序付け要素の数、全体のソート処理が完了するまでこのプロセスが繰り返されます。
図2に示すように、コードの実装
// 多个函数需要用到数据长度,把len设为全局变量
var len;
// 建立大顶堆
function buildMaxHeap(arr) {
len = arr.length;
for(var i = Math.floor(len/2); i >= 0;i--) {
heapify(arr, i);
}
}
// 堆调整
function heapify(arr, i) {
var left = 2 * i + 1,
right = 2 * i + 2,
largest = i;
if (left < len && arr[left] > arr[largest]) {
largest = left;
}
if (right < len && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
swap(arr, i, largest);
heapify(arr, largest);
}
}
function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function HeapSort(arr) {
buildMaxHeap(arr);
}
复制代码
七、マージソート(並び替えマージ)
ソートマージ、それは2つ以上の配列は、プロセスの順序付けられたシーケンスにマージ注文の意味をマージし、「マージ」の並べ替えによる方法です。マージソートの主なアイデア:徐々にマージ順序付けられたシーケンスの数は、最終的に順序付けられたシーケンスにマージ。
1、アルゴリズム記述
- 入力シーケンスの長さNは、長さN / 2の二つのサブシーケンスに分割され、そして
- これら二つの配列をマージソートするために使用されました。
- 最終的なソート順にソートされた2つの合成配列。
図2に示すように、コードの実装
function mergeSort(arr) { //采用自上而下的递归方法
var len = arr.length;
if(len < 2) {
return arr;
}
var middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right) {
var result = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length)
result.push(left.shift());
while (right.length)
result.push(right.shift());
return result;
}
复制代码
八、カウント並べ替え(ソートカウント)
ソートカウント、ソートアルゴリズムは、比較に基づいていない、コアが追加のスペースを開くのアレイに記憶された入力キーにデータ値です。リニアソート時間の複雑さ、要件を注文データ入力数は整数で範囲を決定しなければなりません。
1、アルゴリズム記述
- 最大と最小の要素を見つけるためにソートする配列。
- アレイ内の各要素の数をカウントiはi番目の項目の配列Cに格納され、発生しています。
- 累積カウントの全て(第1の素子Cから出発し、そして添加前一つずつ)。
- ターゲット配列を埋めるリバース:私の各要素の新しい配列C(i)の各要素には、C(I)マイナス1を入れられます。
図2に示すように、コードの実装
function countingSort(arr, maxValue) {
var bucket = new Array(maxValue + 1),
sortedIndex = 0;
arrLen = arr.length,
bucketLen = maxValue + 1;
for (var i = 0; i < arrLen; i++) {
if (!bucket[arr[i]]) {
bucket[arr[i]] = 0;
}
bucket[arr[i]]++;
}
for (var j = 0; j < bucketLen; j++) {
while(bucket[j] > 0) {
arr[sortedIndex++] = j;
bucket[j]--;
}
}
return arr;
}
复制代码
九、バケットソート(バケットソート)
バケットソート、単純な順序付き分布、その動作原理である:入力データが均一に分布され、バケットの限定された数に割り当てられたデータを、各バケットが、再利用することが可能か、別のソートアルゴリズムである(分類したと仮定すると再帰的に)バケットソートを行った行を継続して使用します。
1、アルゴリズム記述
- 定量中空バレルの組として配列。
- 入力されたデータを横断し、バケットに対応するデータが配置します。
- そして、各バケットのソートは空ではありません。
- 一緒にスプライスソートされたデータからではない空のバケツ。
図2に示すように、コードの実装
function bucketSort(arr, bucketSize) {
if (arr.length === 0) {
return arr;
}
var i;
var minValue = arr[0];
var maxValue = arr[0];
for (i = 1; i < arr.length; i++) {
if (arr[i] < minValue) {
minValue = arr[i]; // 输入数据的最小值
} else if (arr[i] > maxValue) {
maxValue = arr[i]; // 输入数据的最大值
}
}
// 桶的初始化
var DEFAULT_BUCKET_SIZE = 5; // 设置桶的默认数量为5
bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;
var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
var buckets = new Array(bucketCount);
for (i = 0; i < buckets.length; i++) {
buckets[i] = [];
}
// 利用映射函数将数据分配到各个桶中
for (i = 0; i < arr.length; i++) {
buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
}
arr.length = 0;
for (i = 0; i < buckets.length; i++) {
insertionSort(buckets[i]); // 对每个桶进行排序,这里使用了插入排序
for (var j = 0; j < buckets[i].length; j++) {
arr.push(buckets[i][j]);
}
}
return arr;
}
复制代码
テン、基数ソート(基数ソート)
基数ソートに応じて低最初にソートし、次いで回収し、次に高いに従ってソートし、次に集め、そしてように、最も高い位置まで。
1、アルゴリズム記述
- アレイの最大数を取得し、ビット数を得ます。
- 元の配列をARR、最下位ビットから基数ビットの各アレイを取るようになりました。
- 計数の基数ソート(小スケール機能の適切な数を使用して配列決定を数えます)。
図2に示すように、コードの実装
var counter = [];
function radixSort(arr, maxDigit) {
var mod = 10;
var dev = 1;
for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
for(var j = 0; j < arr.length; j++) {
var bucket = parseInt((arr[j] % mod) / dev);
if(counter[bucket]==null) {
counter[bucket] = [];
}
counter[bucket].push(arr[j]);
}
var pos = 0;
for(var j = 0; j < counter.length; j++) {
var value = null;
if(counter[j]!=null) {
while ((value = counter[j].shift()) != null) {
arr[pos++] = value;
}
}
}
}
return arr;
}
复制代码
概要
示されるようにソートアルゴリズムの10種類は、以下の要約の比較を行います。
ビューの平均時間の複雑さの点では、高効率低から選別比較の7種類がある:バブルソート挿入ソート≈≈選択ソート<シェルソート<ヒープソート<ソートマージ<クイック
クイックソートは、大規模なデータ値とランダム配置のための最も効率的です。データは、実質的に注文された場合には、効率は、O(N ^ 2)に低下します。
バブルソートは、最も遅いソートアルゴリズム、アルゴリズムの実施において最も低い効率で、時間計算量はO(N ^ 2)です。
並べ替えを選択し実際、バブルソート、ほぼすべて同じ、少ない使用では。
挿入ソートバブルソートよりも早く2回。どこのデータやデータの繰り返し以上の機会に大量の一般適していません。
ヒルソートの約2倍の速さ挿入ソートよりも、バブルソートよりも5倍の速さ。クイックソートよりもシェルソート、マージソート、ヒープソートははるかに遅いです。しかし、シェルアルゴリズムは、特にデータの量のために、比較的簡単で、パフォーマンスが5000以下の場合には非常に高いものではありません。
ヒープ・ソートは、配列データの非常に大量のために適切であるように、必要なまたは一時的な再帰的な多次元配列の多数、交換のためだけスクラッチ空間されていません。
ソートマージ、それは余分な配列を必要とするため、ヒープ・ソートよりも多くのメモリを必要とするので、ソートわずかに速いヒープ以外を。
ソートアルゴリズム深遠なデータ構造が、今私は後であなたと議論していき、その後、他のソートアルゴリズムを学び、そして、一般的なアルゴリズムの10種類をまとめ〜
ます。https://juejin.im/post/5cff4b6ae51d4558936aa05aで再現