미국 자바 스크립트 데이터 구조와 알고리즘 - 버블 정렬, 삽입 정렬, 선택 정렬

미국 자바 스크립트 데이터 구조 및 알고리즘

전체 스택 연습

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) ).

생기

삽입-sort.gif

둘째, 반 삽입 나누

삽입 정렬라는, 또한 최적화 알고리즘입니다 拆半插入.

생각

이진 정렬 배기 아니라 시퀀스 어레이의 제 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. 선택 정렬

생각

정렬 알고리즘 아이디어 선택 실현 삽입 정렬 다소 유사하고, 이것은 정렬 간격과 정렬되지 않은 범위로 분할 될 수있다. 그러나 선택 정렬 정렬 간격으로 최소의 요소를 찾을 수 없을 것 때마다,이 구간의 끝에서 분류 놓습니다.

단계

  1. 먼저, 정렬되지 않은 (대) 소자의 최소 서열을 찾아, 시작 위치는 정렬 된 순서대로 저장된다.
  2. 나머지 분류되지 않은에서 다음 (대형) 요소, 다음 정렬 순서의 마지막에 최소의 요소를 찾기 위해 계속합니다.
  3. 모든 요소는 정렬이 완료 할 때까지 두 번째 단계는 반복된다.

실현

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) ).

생기

선택-sort.gif

개방 제 답변

왜 삽입 정렬은 버블 정렬보다 더 인기?

버블 정렬과 삽입 정렬 시간 복잡도는 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의를 에.

참고 기사 :

추천

출처www.cnblogs.com/biaochenxuying/p/11444593.html