1. 소개
알고리즘은 왕이다.
단지 깊은 내부 강도, 길의 앞쪽 끝 부분이 더 갈 것 전면 먼저 Lianhaoneigong을 배우고 싶다 .
저자가 쓴 자바 스크립트의 미국 자료 구조와 알고리즘 언어와 직렬 인 자바 스크립트 , 엔트리 후 자료 구조와 알고리즘을 쉽게 검토 대상으로.
이유 冒泡排序、选择排序、插入排序
가 O (N-의 평균 시간 복잡도 때문에, 함께 넣어 2 ).
질문을하시기 바랍니다 : 为什么插入排序比冒泡排序更受欢迎 ?
아래를 참조.
2. 정렬 알고리즘을 분석하는 방법
분석의 복잡성은 전체 알고리즘 학습의 본질이다.
- 시간 복잡도 : 촬영 된 알고리즘 실행 시간.
- 우주의 복잡성 : 메모리를 많이 사용하는 프로그램을 실행하기 원하는 크기의 끝.
자세한 시간과 공간의 복잡성은 볼 시간과 공간의 복잡성 - 자바 스크립트 데이터 구조와 미국의 알고리즘을 .
이 알고리즘, 코드 구현을 작동하는 방법 정렬 알고리즘 학습, 우리가 평가하는 방법을 배울 것이 더 중요하다, 배울뿐만 아니라, 정렬 알고리즘을 분석 할 수 있습니다.
에서 정렬 알고리즘의 분석, 执行效率
, 内存消耗
, 稳定性
세 가지 측면.
2.1 효율성
1. 최상의 경우, 최악의 경우, 여기서 평균 시간 복잡도
우리는 정렬 알고리즘의 시간 복잡도를 분석 할 때, 각각, 최상의 경우, 평균 경우의 최악의 경우 시간 복잡도를 제공합니다.
또한 최고에, 원래의 데이터가 최악의 시간 복잡도가 무엇에 해당 정렬 할 말해야한다.
2. 복잡도 계수 시정 저수준
우리는 반응 시간 복잡도 대규모 데이터를 해당 시간의 증가 추세임을 알고 있으므로 나타내는 계수 때 일정한 낮은 레벨을 무시한다.
하지만 실제 소프트웨어 개발, 우리는 종류의, 10, 100, 1000 등 작은 규모의 데이터를, 그래서 알고리즘 정렬 순서 시간 복잡도 대비 동시에 성능에, 우리는 계수 할 수 상수, 낮은 수준도 고려됩니다.
교환 및 번호 (또는 이동) 3. 비교 개수
이 절과 다음은 비교 기준으로 정렬 알고리즘을 말하고있다. 두 연산을 비교의 구현에 기초한 알고리즘을 포함 정렬, 하나의 소자의 크기를 비교하는 다른 요소는 이동 또는 교환된다.
그래서, 우리는 정렬 알고리즘의 효율성을 분석 할 때 경우, 그것은 비교 및 교환 (또는 이동)의 수 있어야한다 번호도 고려됩니다.
2.2 메모리 소비
즉, 공간의 복잡성을 볼 수있다.
또한 다음과 같은 용어를 알아야합니다
- 정렬 : 정렬 모든 작업이 메모리에서 수행된다
- 외부 정렬 상기 데이터가 너무 크고, 따라서, 디스크 데이터, 및 데이터 전송을 통해 정렬 디스크 메모리 일 수 있으므로;
- 시츄 정렬 : 위치 정렬 알고리즘, 공간 복잡도를 참조 O (1) 정렬 알고리즘이다.
그 중에서도 버블 정렬 알고리즘을 정렬 장소입니다.
2.3 안정성
- 안정성 : 시퀀스의 현재 값이 정렬 될 경우
相等
요소 정렬 한 후, 원래의 소자들 사이의 순서는 동일하다不变
.
예를 들어 일본어의 앞에 B 및 A = B, B의 또 앞에 정렬 후; - 불안정 : 시퀀스의 현재 값이 정렬 될 경우
相等
요소 정렬 한 후, 원래의 소자들 사이의 순서는 동일하다改变
.
예를 들어 일본어의 앞에 B 및 A = B, 뒤에 B를 정렬시킨 후,
3. 버블 정렬
생각
- 인접한 두 데이터 버블 정렬이 작동합니다.
- 인접한 두 요소에 작동 할 때마다 기포가 관계의 크기 요구 사항을 만족하는지 비교한다. 그렇지 않은 경우, 탈리아는 상호 교환 할 수 있습니다.
- 적어도 하나 개의 요소가 그 위치로 이동 버블 메이크업은 N의 작업 데이터를 정렬 완료, N 회 반복한다.
특징
- 장점 : 기본 정렬 알고리즘은 이해하기 쉽고 간단하고 실용적입니다.
- 단점 : 상대적으로 더 자주, 덜 효율적.
실현
// 冒泡排序(未优化)
const bubbleSort = arr => {
console.time('改进前冒泡排序耗时');
const length = arr.length;
if (length <= 1) return;
// i < length - 1 是因为外层只需要 length-1 次就排好了,第 length 次比较是多余的。
for (let i = 0; i < length - 1; i++) {
// j < length - i - 1 是因为内层的 length-i-1 到 length-1 的位置已经排好了,不需要再比较一次。
for (let j = 0; j < length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
const temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log('改进前 arr :', arr);
console.timeEnd('改进前冒泡排序耗时');
};
최적화 : 특정 작업이 데이터 교환 거품 없었다 때, 설명은 충분히 더 이상 후속 버블 링 작업을 계속 수행하지, 주문에 도달했습니다.
// 冒泡排序(已优化)
const bubbleSort2 = arr => {
console.time('改进后冒泡排序耗时');
const length = arr.length;
if (length <= 1) return;
// i < length - 1 是因为外层只需要 length-1 次就排好了,第 length 次比较是多余的。
for (let i = 0; i < length - 1; i++) {
let hasChange = false; // 提前退出冒泡循环的标志位
// j < length - i - 1 是因为内层的 length-i-1 到 length-1 的位置已经排好了,不需要再比较一次。
for (let j = 0; j < length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
const temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
hasChange = true; // 表示有数据交换
}
}
if (!hasChange) break; // 如果 false 说明所有元素已经到位,没有数据交换,提前退出
}
console.log('改进后 arr :', arr);
console.timeEnd('改进后冒泡排序耗时');
};
테스트
// 测试
const arr = [7, 8, 4, 5, 6, 3, 2, 1];
bubbleSort(arr);
// 改进前 arr : [1, 2, 3, 4, 5, 6, 7, 8]
// 改进前冒泡排序耗时: 0.43798828125ms
const arr2 = [7, 8, 4, 5, 6, 3, 2, 1];
bubbleSort2(arr2);
// 改进后 arr : [1, 2, 3, 4, 5, 6, 7, 8]
// 改进后冒泡排序耗时: 0.318115234375ms
분석
- 첫째, 버블 정렬은 장소 알고리즘이 어떻게 분류 되는가?
버블 링 처리는 단지 인접한 데이터 교환 동작을 수반 공간 복잡도는 O (1)와,이되도록 단지 임시 공간이 일정 레벨을 필요로原地
정렬 알고리즘. - 둘째, 버블 정렬은 안정적인 정렬 알고리즘이 할 무엇입니까?
버블 분류, 교환은 두 개의 길이 요소의 순서를 변경할 수있다.
동일한 크기의 두 인접하는 요소가 버블 소트 알고리즘의 안정성을 보장하기 위해,에서는 교환 전과 선별 후 변경되지 않는 데이터의 순서와 동일한 순서의 크기를 수행.
그래서 거품 정렬은이다稳定
정렬 알고리즘. - 셋째, 버블 정렬의 시간 복잡도는 얼마입니까?
최상의 경우 : T (N) = O ( n)은, 데이터가 이미 긍정적 인 시퀀스이다.
최악의 경우 : T (N-) = O (N- (2) 데이터가 역순이다).
보통의 경우 : T (N-) = O (N- (2) ).
생기
4. 삽입 정렬
그리고 삽입 정렬은으로 나누어 져 일종의 직접 삽입 후와 최적화 반 삽입 정렬의 철거 및 쉘 정렬을 우리가 일반적으로 말하는 삽입 정렬은 직접 삽입 정렬을 의미한다.
첫째, 직접적으로
생각
카드 크기에 의해 (소형에서 대형에 작은 대형에서) 마무리 카드 때 대부분의 사람들은 모든 새 카드를 접촉하는 것이, 그들이 적절한으로, 새로운 카드를 자신의 카드를 스캔 카드를 정렬, 포커 위치.
다시 전면에서 정렬 된 순서대로 정렬되지 않은 데이터, 스캔, 정렬 순서를 구성하여, 및 해당 삽입 위치를 찾을 수 : 삽입 정렬 작동합니다.
단계
- 분류 된 것으로 간주 될 수있는 첫 번째 요소로 시작;
- 소자의 순서로 정렬 된 전방 스캔에서 다음 요소를 제거;
- 소자 (정렬)는 새로운 요소를 다음 위치로 소자보다 크면;
- 3 단계를 반복은 이하 요소의 새로운 위치와 동일한 정렬 요소를 발견 할 때까지;
- 새로운 요소는이 위치에 삽입 한 후에;
- 반복 2-5 단계를 반복합니다.
실현
// 插入排序
const insertionSort = array => {
const len = array.length;
if (len <= 1) return
let preIndex, current;
for (let i = 1; i < len; i++) {
preIndex = i - 1; //待比较元素的下标
current = array[i]; //当前元素
while (preIndex >= 0 && array[preIndex] > current) {
//前置条件之一: 待比较元素比当前元素大
array[preIndex + 1] = array[preIndex]; //将待比较元素后移一位
preIndex--; //游标前移一位
}
if (preIndex + 1 != i) {
//避免同一个元素赋值给自身
array[preIndex + 1] = current; //将当前元素插入预留空位
console.log('array :', array);
}
}
return array;
};
테스트
// 测试
const array = [5, 4, 3, 2, 1];
console.log("原始 array :", array);
insertionSort(array);
// 原始 array: [5, 4, 3, 2, 1]
// array: [4, 5, 3, 2, 1]
// array: [3, 4, 5, 2, 1]
// array: [2, 3, 4, 5, 1]
// array: [1, 2, 3, 4, 5]
분석
- 첫째, 삽입 정렬 알고리즘을 대신 거기에있다 정렬?
삽입 정렬 작업이 추가 저장 공간을 필요로하지 않습니다, 공간 복잡도는 (1) O, 그래서 이것은이다原地
정렬 알고리즘. - 둘째, 삽입 정렬은 안정적인 정렬 알고리즘이 할 무엇입니까?
및 변경 후, 그것은 삽입 정렬되기 전에 원래의 질서를 유지 할 수 있도록 정렬 삽입, 같은 요소 값, 우리는 나중에 표시됩니다 요소를 선택할 수 있습니다, 전면 요소의 뒷면 발생에 삽입稳定
정렬 알고리즘의가. - 셋째, 삽입 정렬의 시간 복잡도는 얼마입니까?
최상의 경우 : T (N) = O ( n)은, 데이터가 이미 긍정적 인 시퀀스이다.
최악의 경우 : T (N-) = O (N- (2) 데이터가 역순이다).
보통의 경우 : T (N-) = O (N- (2) ).
생기
둘째, 반 삽입 나누
삽입 정렬라는, 또한 최적화 알고리즘입니다 拆半插入
.
생각
이진 정렬 배기 아니라 시퀀스 어레이의 제 1 부분의 정렬, 삽입 정렬 뷰의 업그레이드 된 버전에 직접 삽입되고, 우리는 단순히 그 소자의 크기가 삽입 될 수있는 중간 값을 비교하고, 순서에 따라 삽입 포인트를 찾을 수 없다.
단계
- 중간 지점을 촬영 (m은 = (I-1) >> 1) 0 ~ 어레이 [i]는 어레이 [m] 비교 어레이는 [I] [m]는 <어레이는 그것이 삽입 수단 I-1 인 경우 소자 어레이는 [I]는 0 ~ m 배열 인덱스 사이 여야하고, 그렇지 않으면, 그것은 m 사이 것을 나타낸다 ~ I-1 어레이 인덱스.
- 반복 삽입 될 때까지의 위치를 찾기 위해 한 좁은 범위 조회 각각 절반 단계.
- 모든 역방향 하나의 삽입 위치 뒤에 배열 요소.
- I 번째 요소는 지정된 위치에 삽입된다.
주 : X >> 1 동작에서 오른쪽 시프트 연산하고, 즉, X, 우측 시프트를 나타내고, X 2로 나눔에 해당하고 둥근 >> == 1 Math.floor (X / 2).
// 折半插入排序
const binaryInsertionSort = array => {
const len = array.length;
if (len <= 1) return;
let current, i, j, low, high, m;
for (i = 1; i < len; i++) {
low = 0;
high = i - 1;
current = array[i];
while (low <= high) {
//步骤 1 & 2 : 折半查找
m = (low + high) >> 1; // 注: x>>1 是位运算中的右移运算, 表示右移一位, 等同于 x 除以 2 再取整, 即 x>>1 == Math.floor(x/2) .
if (array[i] >= array[m]) {
//值相同时, 切换到高半区,保证稳定性
low = m + 1; //插入点在高半区
} else {
high = m - 1; //插入点在低半区
}
}
for (j = i; j > low; j--) {
//步骤 3: 插入位置之后的元素全部后移一位
array[j] = array[j - 1];
console.log('array2 :', JSON.parse(JSON.stringify(array)));
}
array[low] = current; //步骤 4: 插入该元素
}
console.log('array2 :', JSON.parse(JSON.stringify(array)));
return array;
};
테스트
const array2 = [5, 4, 3, 2, 1];
console.log('原始 array2:', array2);
binaryInsertionSort(array2);
// 原始 array2: [5, 4, 3, 2, 1]
// array2 : [5, 5, 3, 2, 1]
// array2 : [4, 5, 5, 2, 1]
// array2 : [4, 4, 5, 2, 1]
// array2 : [3, 4, 5, 5, 1]
// array2 : [3, 4, 4, 5, 1]
// array2 : [3, 3, 4, 5, 1]
// array2 : [2, 3, 4, 5, 5]
// array2 : [2, 3, 4, 4, 5]
// array2 : [2, 3, 3, 4, 5]
// array2 : [2, 2, 3, 4, 5]
// array2 : [1, 2, 3, 4, 5]
注意
: 직접 삽입 정렬 등 이진 삽입 정렬은 따라서 안정 각 교환 및 다른 요소의 값은, 그 요소 사이에 같은 값의 순서를 변경하지 않는 인접.
셋째, 힐 정렬
쉘 정렬 O (nlogn) 알고리즘의 평균 시간 복잡도이며, 다음 장 수와 종류, 빠른 정렬, 힙 정렬 함께 말하자면, 그것은 시작되지 않습니다 병합합니다.
5. 선택 정렬
생각
정렬 알고리즘 아이디어 선택 실현 삽입 정렬 다소 유사하고, 이것은 정렬 간격과 정렬되지 않은 범위로 분할 될 수있다. 그러나 선택 정렬 정렬 간격으로 최소의 요소를 찾을 수 없을 것 때마다,이 구간의 끝에서 분류 놓습니다.
단계
- 먼저, 정렬되지 않은 (대) 소자의 최소 서열을 찾아, 시작 위치는 정렬 된 순서대로 저장된다.
- 나머지 분류되지 않은에서 다음 (대형) 요소, 다음 정렬 순서의 마지막에 최소의 요소를 찾기 위해 계속합니다.
- 모든 요소는 정렬이 완료 할 때까지 두 번째 단계는 반복된다.
실현
const selectionSort = array => {
const len = array.length;
let minIndex, temp;
for (let i = 0; i < len - 1; i++) {
minIndex = i;
for (let j = i + 1; j < len; j++) {
if (array[j] < array[minIndex]) {
// 寻找最小的数
minIndex = j; // 将最小数的索引保存
}
}
temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
console.log('array: ', array);
}
return array;
};
테스트
// 测试
const array = [5, 4, 3, 2, 1];
console.log('原始array:', array);
selectionSort(array);
// 原始 array: [5, 4, 3, 2, 1]
// array: [1, 4, 3, 2, 5]
// array: [1, 2, 3, 4, 5]
// array: [1, 2, 3, 4, 5]
// array: [1, 2, 3, 4, 5]
분석
- 첫째, 정렬 알고리즘을 정렬 장소를 선택 하는가?
선택 정렬 공간 복잡도는 O (1), A는原地
정렬 알고리즘. - 둘째, 선택 정렬은 안정적인 정렬 알고리즘이 할 무엇입니까?
선택 나머지 요소 찾고마다 정렬하지 정렬 최소값 정면 소자와 교환 위치, 즉 손상 안정성 때문에. 그래서 선택 정렬은이다不稳定
정렬 알고리즘. - 얼마나 셋째, 정렬 시간 복잡도는 선택?
그것이 긍정적 또는 순서를 반대로 여부, 선택 정렬은 N-를 통과 할 이 최고, 최악의 평균 복잡성이 동일하므로, 정렬 / 2 번.
최상의 경우 : T (N-) = O (N- (2) ).
최악의 경우 : T (N-) = O (N- (2) ).
보통의 경우 : T (N-) = O (N- (2) ).
생기
개방 제 답변
왜 삽입 정렬은 버블 정렬보다 더 인기?
버블 정렬과 삽입 정렬 시간 복잡도는 O (N- 형 2 ), 삽입 정렬 이유는 일종의 거품보다 더 인기가 정렬 알고리즘 현장에있다?
여기서 상기 역방향 풀 오더 정도의 오더 정도에 관한 것이다.
- 순서의 유무 : 배열의 요소 수는 순서쌍 관계이다.
수식을 나타내는 정렬 요소이있다 :
有序元素对:a[i] <= a[j], 如果 i < j。
순서의 전체 수준 : 완전히 정렬 된 배열의 순서는 호출 순서의 전체 학위를 .
- 역 정도 : 위해의 정도 (작은에서 많은에 대한 기본 순서)와 그 반대.
逆序元素对:a[i] > a[j], 如果 i < j。
마찬가지로, 6,5,4,3,2,1 등의 역순으로 배열에 대해, 순서화의 정도가 0이며,
완전히 정렬 된 어레이, 예컨대 1,2,3,4,5,6, 정렬의 정도가 ** * N 개 (N-1) / 2 ** 순서의 전체도 (15)이다.
이유
- 아무리 거품 정렬을 최적화하는 방법, 스위치 소자의 수는 고정 된 값이없는 원래의 데이터의 역이다.
- 삽입 정렬은 최적화 이동 요소의 수는 원래 데이터의 역순으로 동일한 방법에 상관없이, 동일한 없다.
- 그러나, 복잡한 데이터 이동, 거품 정렬 삽입 정렬보다 데이터 교환의 거품 정렬 세 할당을 요구하고, 단지 하나의 삽입 정렬 데이터의 일단 다량이 필요하며,이 차이는 매우 명백하다.
제 복잡성 비교
비교의 복잡성
이름 | 평균 | 가장 좋은 | 최악 | 공간 | 안정 | 정렬 |
---|---|---|---|---|---|---|
버블 정렬 | O (N 2 ) | O (n) | O (N 2 ) | O (1) | 예 | 현재 위치에서 |
삽입 정렬 | O (N 2 ) | O (n) | O (N 2 ) | O (1) | 예 | 현재 위치에서 |
선택 정렬 | O (N 2 ) | O (N 2 ) | O (N 2 ) | O (1) | 아니 | 현재 위치에서 |
알고리즘 시각화 도구
그것은 시각적 도구 알고리즘을하는 것이 좋습니다.
알고리즘 시각화 도구 알고리즘 시각화는 알고리즘이 코드에서 시각화 할 수있는 쌍방향 온라인 플랫폼입니다, 당신은 또한 코드 실행의 과정을 볼 수 있습니다.
그림과 같이 결과.
8. 마지막으로
그것의 지점에 작은 별처럼.
코드와 테스트의 경우 텍스트의 모든 이미 내 뒀다 GitHub의를 에.
참고 기사 :