삽입 정렬과 버블 정렬 알고리즘


85

몇 가지 정렬 알고리즘을 이해하려고 노력하고 있지만 버블 정렬과 삽입 정렬 알고리즘의 차이점을 확인하는 데 어려움을 겪고 있습니다.

나는 둘 다 O (n 2 ) 라는 것을 알고 있지만 버블 정렬은 각 패스에 대해 배열의 최대 값을 맨 위로 버블 링하는 반면 삽입 정렬은 각 패스에서 가장 낮은 값을 맨 아래로 싱크합니다. 그들은 똑같은 일을하지만 다른 방향으로하고 있지 않습니까?

삽입 정렬의 경우 비교 / 잠재적 스왑 수는 0에서 시작하여 매번 증가하지만 (예 : 0, 1, 2, 3, 4, ..., n) 버블 정렬의 경우 이와 동일한 동작이 발생하지만 정렬 (즉, n, n-1, n-2, ... 0)은 버블 정렬이 정렬 될 때 마지막 요소와 더 이상 비교할 필요가 없기 때문입니다.

이 모든 것에 대해 일반적으로 삽입 정렬이 더 좋다는 것이 합의 된 것 같습니다. 아무도 이유를 말해 줄 수 있습니까?

편집 : 저는 주로 알고리즘의 효율성이나 점근 적 복잡성이 아니라 알고리즘 작동 방식의 차이점에 관심이 있습니다.


1
이것은 다른 곳에서 잘 문서화되어 있습니다 : 예를 들어 en.wikipedia.org/wiki/Sorting_algorithm을 참조하십시오 . 여기서 복제하는 것은 무의미하며 좋은 대답은 광범위 할 것입니다.
Bathsheba

@Bathsheba 찬성 한 75 명과 질문을 본 88k는 동의하지 않는 것 같습니다. )
parsecer

@parsecer : 하! 이제 답을 검토해야합니다. 현재 가장 높은 찬성 응답이 유용합니다. 다른 사람들에 대해서는 확실하지 않습니다. 여기에 답안 투표로 인해 잃어버린 일부 담당자 점수가 있습니다. 수락 된 답변의 "삽입 정렬이 버블 정렬보다 빠른 이유입니다"라는 주장이 반드시 사실은 아닙니다.
밧세바

@Bathsheba Oh no
parsecer

답변:


38

ith 반복의 거품 정렬에서는 ni-1 내부 반복 (n ^ 2) / 2 total이 있지만 삽입 정렬에서는 i 번째 단계에서 최대 i 반복이 있지만 내부 루프를 중지 할 수 있으므로 평균적으로 i / 2가 있습니다. 이전에는 현재 요소의 올바른 위치를 찾은 후. 따라서 (0에서 n까지의 합계) / 2는 (n ^ 2) / 4 합계입니다.

이것이 삽입 정렬이 버블 정렬보다 빠른 이유입니다.


2
알고리즘 설명은 웹 어디에나 있다고 생각합니다.
sasha.sochka

3
네,하지만 영업 이익은 여전히 메커니즘 캐치 차이가 나던 것
UmNyobe

15
내가 기본을 이해한다고 가정 할 수 있습니다 . 제가 원했던 것은 비교였습니다. 이것은 정말 좋습니다. 따라서 삽입 정렬로 인해 i 번째 요소가 아래로 가라 앉고 버블 정렬로 인해 버블 링되지만 삽입 정렬로 인해 맨 아래로 떨어지지 않고 올바른 위치로 떨어지게됩니다. 이미 정렬 된 섹션. 따라서 비교 / 스왑이 적습니다. 맞습니까?
Migwell

1
뭐? "그래서 당신은 (0에서 n까지의 합) / 2는 (n ^ 2) / 총 4입니다"그것은 약간의 expl이 필요합니다! 0 + 1 + 2 + 3 + 4 + 5 = 15; 15 / 2 = 7.5; 7.5 * 4 = 30; SQRT (30) = 횡설수설
존 스미스

@JohnSmith 대답에 약간의 오류가 있다고 생각합니다. 1에서 n까지의 합은 삼각형 숫자이므로 n * (n + 1) / 2입니다. 자세한 설명은 삼각형 숫자를 찾으십시오. 2로 나눈 것은 n * (n + 1) / 2입니다.
CognizantApe

121

삽입 정렬

이후 첫번째 반복 I를 요소는 정렬된다.

각 반복에서 다음 요소는 올바른 지점에 도달 할 때까지 정렬 된 섹션을 통해 버블 링됩니다 .

sorted  | unsorted
1 3 5 8 | 4 6 7 9 2
1 3 4 5 8 | 6 7 9 2

4는 정렬 된 섹션에 버블 링됩니다.

의사 코드 :

for i in 1 to n
    for j in i downto 2
        if array[j - 1] > array[j]
            swap(array[j - 1], array[j])
        else
            break

버블 정렬

후에 내가 반복 마지막으로 내가 요소가 가장 큰를하고, 명령했다.

각 반복에서 정렬되지 않은 섹션을 선별 하여 최대 값을 찾습니다.

unsorted  | biggest
3 1 5 4 2 | 6 7 8 9
1 3 4 2 | 5 6 7 8 9

5는 정렬되지 않은 섹션에서 버블 링됩니다.

의사 코드 :

for i in 1 to n
    for j in 1 to n - i
         if array[j] > array[j + 1]
             swap(array[j], array[j + 1])

일반적인 구현은 외부 루프의 반복 중 하나 동안 스왑이 수행되지 않으면 조기에 종료됩니다 (배열이 정렬됨을 의미하기 때문).

삽입시 정렬 요소는 정렬 된 섹션으로 버블 링되는 반면 버블 정렬에서는 최대 값이 정렬되지 않은 섹션에서 버블 링됩니다.


10
감사합니다. 이것은 매우 명확합니다! 내가 강조해야 할 중요한 점 은 Insertion Sort 의 break 문이 각 반복을 일찍 종료 할 수 있다는 것입니다. 즉, 정렬 된 섹션에서 위치를 찾았을 때입니다. 버블 정렬은 정렬되지 않은 섹션의 가장 큰 요소가 정렬 된 섹션에 도달 할 때까지 스왑이 계속되어야하므로 조기에 종료되지 않습니다. 이 환상적인 요약입니다하지만, +1 때문에
Migwell

4
나는 이것이 최선의 대답이어야한다고 생각합니다. :)
Adelin 2014-04-29

2
명확성, 교훈적 가치 각 알고리즘의 주요 루프 불변에 대해 1을 더합니다. 복잡도 ( n 의 함수로 표현됨)의 비교를 명시 적으로 포함하지 않는 것은 유감입니다. 어쨌든 나는 그것이 받아 들여진 것보다 더 나은 대답이라고 생각합니다. 왜냐하면 이것으로부터 나는 차이를 수 있기 때문입니다.
Honza Zidek

모든 단계에서 삽입 의사 코드에서 항목을 교체하는 이유는 무엇입니까? if (a [j-1]> a [j]) then a [j] = a [j-1] ELSE if (a [j-1] <e && a [j]> e) than a [j] = e; 휴식; , 여기서 e는 정렬해야하는 항목입니다. 이 솔루션을 사용하면 이미 정렬 된 항목을 바꾸지 않고 복사 만 할 수 있습니다. 내가 약간 혼란 스럽기 때문에 설명을 기대합니다.
Karoly

@Karoly, 더 간단하기 때문에 내 버전을 선택했습니다. 당신의 것이 약간 빠르며 지적하는 것이 좋습니다. Wikipedia 는 두 버전을 모두 설명합니다.
tom

16

또 다른 차이점은 여기에서 보지 못했습니다.

버블 정렬 에는 스왑 당 3 개의 값 할당이 있습니다. 이 있습니다. 방금 값을 저장 한 지점에 다른 스왑 변수를 작성해야하는 것보다 먼저 푸시하고 싶은 값 (1 번)을 저장하기 위해 임시 변수를 만들어야합니다. of (no.2) 그런 다음 다른 자리 (no.3)에 임시 변수를 작성해야합니다. 변수를 올바른 지점으로 정렬하려면 각 지점에 대해이를 수행해야합니다.

삽입 정렬 을 사용하면 변수를 임시 변수에 정렬 한 다음 변수의 올바른 지점에 도달하는 한 모든 변수를 해당 지점 앞에 1 지점 뒤로 놓습니다. 즉 , 스팟 당 1 개의 값 할당 합니다. 결국 임시 변수를 그 자리에 씁니다.

이는 가치 할당도 훨씬 적습니다.

이것은 가장 강력한 속도 이점은 아니지만 언급 할 수 있다고 생각합니다.

나는 이해하기를 바란다. 그렇지 않다면 미안하다. 나는 영국 출신이 아니다.


1
"그런 다음 모든 변수를 그 자리 1 자리 뒤로 배치합니다."— 데이터를 이동하기 위해 많은 할당이 필요하지 않습니까? (데이터를 가정하는 것은 링크리스트 어쨌든 연속 저장)
마크 K 코완

@MarkKCowan, 예, 위의 사용자가 입력 한 것처럼 삽입 정렬이 '스팟'별로 할당하는 곳입니다. 기본적으로 삽입 정렬은 내부 루프에 하나의 할당으로 작성할 수 있으며, 버블 정렬에는 내부 루프에 3 개의 할당이 있습니다.
JSQuareD

9

삽입 정렬의 주요 장점은 온라인 알고리즘이라는 것입니다. 처음에 모든 값을 가질 필요는 없습니다. 이는 네트워크 또는 일부 센서에서 오는 데이터를 처리 할 때 유용 할 수 있습니다.

나는 이것이 다른 기존 n log(n)알고리즘 보다 빠르다는 느낌이 있습니다 . 복잡성은 n*(n log(n))스트림 ( O(n)) 에서 각 값을 읽고 / 저장 한 다음 모든 값을 정렬 (O(n log(n)) ) 하여O(n^2 log(n))

반대로 Insert Sort를 사용 O(n)하려면 스트림에서 값을 읽고 값을 O(n)올바른 위치에 배치해야하므로 그럴 O(n^2)뿐입니다. 다른 장점은 값을 저장하는 데 버퍼가 필요하지 않고 최종 대상에서 정렬한다는 것입니다.


데이터의 순차 순회가 단순히 배열을 스캔하는 것 이외의 다른 것이 괜찮다면 훨씬 더 효율적으로 즉석에서 정렬 할 수 있습니다. 예를 들어,받은대로 이진 트리에 요소를 삽입합니다. 이렇게하면 O(n log(n))모든 단계에서 컬렉션을 정렬하기 위해 수행 된 전체 작업 이 제공 됩니다. (모든 지점에서 순회 순회는입니다 O(m)). 마지막에 정렬 된 결과 만 필요하지만 정렬 계산을 데이터 전송 시간과 겹치고 싶다면 힙이 좋을 수 있습니다. (그리고 삽입 정렬과 같이 제자리에서 작동합니다).
Peter Cordes

어쨌든, 버블 정렬도 삽입 정렬도 O(f(n))구현 세부 사항 및 상수 요인보다 복잡도 클래스가 더 중요 할만큼 충분히 큰 문제 크기를 사용하는 데 이상적입니다 .
Peter Cordes 2017

정정 : 은 이에 적합하지 않습니다. 정렬 된 순서로 요소를 제거 할 때 대부분의 정렬 작업을 수행하므로 성장이 매우 저렴합니다. 여기서의 목표는 마지막 요소가 도착할 때까지 대부분의 작업을 완료하는 것입니다.
Peter Cordes

어쨌든, n삽입 을 위해 정렬 된 배열을 유지해야 했다면 실제로는 정렬되지 않은 요소가 맨 위에있는 거의 정렬 된 배열을 정렬하는 데 가장 적합한 알고리즘이 무엇인지로 귀결됩니다. 많은 O(n log(n))정렬 알고리즘이 O(n)거의 정렬 된 경우이므로 sum(M=1..n, O(M * log(M)) )작업이 필요하다는 것은 사실이 아닙니다 . 그것은 실제로 O(n^2 log(n))이지만 알고리즘을 올바르게 선택하면 O(n^2)전체 작업 이 될 것입니다. 그러나 삽입 정렬이 가장 효율적입니다.
Peter Cordes

7

버블 정렬은 정렬 된 요소의 전역 최대 값을 실제로 추적하지 않기 때문에 온라인이 아닙니다 (항목 수를 알지 못하면 입력 스트림을 정렬 할 수 없습니다). 항목이 삽입되면 처음부터 버블 링을 시작해야합니다.


4

잘 거품 정렬은 누군가가 큰 숫자 목록에서 상위 k 요소를 찾을 때만 삽입 정렬보다 낫습니다. 즉, k 반복 후 거품 정렬에서 상위 k 요소를 얻을 수 있습니다. 그러나 삽입 정렬에서 k 반복 후에는 해당 k 요소가 정렬되도록 보장합니다.


2

두 정렬 모두 O (N ^ 2)이지만, 삽입 정렬에서 숨겨진 상수는 훨씬 더 작습니다. 숨겨진 상수는 수행 된 실제 기본 연산 수를 나타냅니다.

삽입 정렬이 더 나은 실행 시간을 가질 때?

  1. 배열은 거의 정렬되어 있습니다.이 경우 삽입 정렬은 버블 정렬보다 적은 작업을 수행합니다.
  2. 배열은 상대적으로 작은 크기입니다 : 현재 요소를 배치하기 위해 요소를 이동하는 삽입 정렬. 요소 수가 적은 경우에만 버블 정렬보다 낫습니다.

삽입 정렬이 항상 버블 정렬보다 좋은 것은 아닙니다. 두 가지 장점을 모두 얻으려면 배열이 작은 경우 삽입 정렬을 사용하고 더 큰 배열의 경우 병합 정렬 (또는 빠른 정렬)을 사용할 수 있습니다.


2
요소 수가 적지 않은 경우 버블 정렬이 어떻게 더 좋을까요? 내 이해는 IS에서 슬라이드하든 BS에서 스왑하든 비교되는 요소가 요소 수가 아니라 더 큰지 (IS) 더 작은 지 (BS)에 따라 달라진다는 것입니다. 틀렸다면 정정 해주세요.
무스타파

0

버블 정렬은 모든 상황에서 거의 쓸모가 없습니다. 삽입 정렬에 너무 많은 스왑이있을 수있는 사용 사례에서는 N 배 미만의 스왑을 보장하므로 선택 정렬을 사용할 수 있습니다. 선택 정렬이 버블 정렬보다 낫기 때문에 버블 정렬에는 사용 사례가 없습니다.


0

각 반복의 스왑 수

  • 삽입 정렬은 각 반복에서 최대 1 개의 스왑을 수행합니다. 합니다.
  • Bubble-sort는 각 반복에서 0에서 n 개의 스왑을 수행합니다.

정렬 된 부품 액세스 및 변경

  • 삽입 정렬은 정렬 된 부분에 액세스 (필요한 경우 변경)하여 고려중인 숫자의 올바른 위치를 찾습니다.
  • 최적화되면 Bubble-sort는 이미 정렬 된 항목에 액세스하지 않습니다.

온라인 여부

  • 삽입 정렬이 온라인 상태입니다. 즉, Insertion-sort는 적절한 위치에 놓기 전에 한 번에 하나의 입력을 받습니다 . 단지 비교할 필요는 없습니다 adjacent-inputs.
  • Bubble-sort는 온라인이 아닙니다. 한 번에 하나의 입력을 작동하지 않습니다. 각 반복에서 입력 그룹 (전부는 아님)을 처리합니다. 버블 정렬 은 각 반복 에서만 비교하고 교환adjacent-inputs 합니다.

0

삽입 정렬 :

1. 삽입 정렬 교환이 필요하지 않습니다.

2. 삽입 정렬의 시간 복잡도는 최상의 경우 Ω (n), 최악의 경우 O (n ^ 2)입니다.

3. 버블 정렬에 비해 덜 복잡합니다.

4. 예 : 도서관에 책을 넣고 카드를 정리합니다.

버블 정렬 : 1. 버블 정렬에서 교체가 필요합니다.

2. 버블 정렬의 시간 복잡도는 최상의 경우 Ω (n), 최악의 경우 O (n ^ 2)입니다.

3. 삽입 정렬에 비해 더 복잡합니다.


1
왜 스와핑이 필요하지 않습니까? 요소를 교체하여 요소를 올바른 위치에 놓습니다. 그리고 나는 버블 정렬이 더 복잡하다고 말하지 않을 것입니다.
파세 서

-1

삽입 정렬은 " 첫 번째 위치 (최소)에 있어야 할 요소를 찾고 다음 요소를 이동하여 공간을 확보 한 후 첫 번째 위치에 놓으십시오. 좋습니다. 이제 두 번째 위치에 있어야하는 요소를보십시오. ... "등등 ...

버블 정렬은 다르게 작동하며 " 순서가 잘못된 두 개의 인접한 요소를 찾으면 서로 바꿉니다."로 다시 시작할 수 있습니다 .


그것은 삽입 정렬에 도움이되지만 거품 정렬에 대한 설명에는 실제 루프가 포함되어 있지 않으므로 실제로 비교할 수는 없습니다. 삽입 정렬도 효과적으로 규칙을 가지고 있습니다. 잘못된 순서로 된 두 개의 인접한 요소를 찾는 한 그것들을 교체합니다 . 루프가 작동하는 방식이 다릅니다.
Migwell

3
그 선택 정렬 아닌가요?
해롤드

아 그래 그건 사실 ^입니다
Migwell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.