1 간단한 정렬 (버블, 삽입)
정렬 횟수가 10,000 개 이상이면 효율성이 매우 중요합니다.
1.1 전제 조건
정렬 할 요소는 배열 (A [])에 저장되고 N은 정렬 할 숫자의 수를 나타냅니다.
내부 정렬 : 메모리 공간이 충분히 크다고 가정하면 모든 숫자가 메모리로 전달됩니다. 모든 숫자의 정렬은 메모리에서 수행됩니다.
1.2 버블 정렬
목적은 가장 작은 거품을 위쪽으로, 가장 큰 거품을
아래쪽 으로 정렬하는 것입니다 . 2 개의 거품 (0 번째 및 1 번째)을 위에서 아래로 비교합니다. 작은 거품이 위쪽에 있고 큰 거품이 아래쪽에있는 경우 그렇지 않으면이 두 거품을 교체
한 다음 아래로 내려 가서 인접한 두 개의 거품 (첫 번째와 두 번째)
을 끝 과 비교하고 아래 그림과 같이 첫 번째 정렬을 완료하고 첫
번째 통과 후 정렬을 완료합니다. 가장 큰 것은 맨 아래에 있어야합니다. 두
번째 패스는 이전 n-1을 반복합니다.
그러나 운이 좋으면 위의 특정 패스에 대한 정렬 순서가 정렬됩니다. 즉, 특정 패스에 대한 교환 순서가 없습니다 ( 스왑 기능 실행)
최상의 경우 : 한 번만 스캔
최악의 경우 : 작은 것에서 큰 것까지 정렬하지만 큰 것에서 작은 것까지 정렬
이점 :
1. 단순함
2. 링크드 목록에도 동일하게 적용됨 (다른 정렬도 가능하지 않음) ) 그렇게
는 정렬 알고리즘의 안정성을 보장하기 위해 엄격하게보다 큰 스왑 3. 때만.
단점 다음으로
, 최악의 경우, 시간 복잡도는 O (N 인 2 용인)의
1.3 삽입 정렬
카드 놀이 처음
에 0 번째 카드가 이미 당신의 손에 있다고 가정합니다
. 뒤에서 앞으로 비교하십시오. 위치를 찾으면이 위치와 다음 카드를 하나씩 뒤로 이동하십시오.
장점 :
1. 단순
2. 3을 사용하십시오. 단계적으로 삽입 정렬 단계는 단 하나의 단계로 더 간단
하고 안정적
이며 4 단계로
불리합니다.
1.4 시간 복잡도의 하한
버블 링 및 삽입 교환의 순서는 9 회이며, 역 쌍이 제거 될 때마다
순서는 기본적으로 순서가 지정됩니다. 즉, I가 작으며 정렬 알고리즘이 매우 빠릅니다.
Omega : Lower Bound
2 언덕 정렬
삽입 정렬의 단순성을 활용하되 매번 하나의 역방향 쌍만 제거하는 단점을 극복
하십시오. a-interval 정렬 (먼저
a로 구분 된 숫자 정렬) , b-interval 정렬
및 c-interval 정렬을 수행하십시오
. . .
1 간격 정렬
a> b> c>를 수행합니다 .. . . > 1
매우 중요한 속성 : 다음 인터벌이 정렬 된 후
이전 인터벌의 특성이 유지됩니다. 원래 삽입 정렬은 0 번째 카드가 이미 핸드에 있고 인터벌 1 카드
의 순서 는 다음과 같습니다. D 카드가 손에 있다는 것 인터벌 D 카드의 순서는
상한과 하한입니다.
수만 개의 숫자에 대해 Hill + Sedgewick의 복잡성은 상대적으로 낮습니다.
레코드가 점프와 정렬로 이동하기 때문에 불안정 합니다. 방법이 불안정합니다.
3 힙 정렬
3.1 선택 정렬
처음부터 순서대로 가장 작은 요소를 찾아 맨 앞에 놓은 다음이 위치에서 가장 작은 요소를 찾아서 바로 뒤에
놓습니다 .Swap (A [i], A [MinP]) : 숫자 교류 서로 옆하지 않을
교환시 복잡도가 선형 (O (N)). 그래서, 최악의 경우, 그 때마다 변경할 필요가
찾기 작은 소자 ScanForMin ()가 또한 루프를 들면,
그래서 상관없이 가장 좋은 경우와 최악의 경우는 O (N 2 )
가장 작은 요소를 빠르게 찾는 방법은 무엇입니까? 힙 정렬 사용 가능
3.2 힙 정렬
선택 정렬 개선
알고리즘 1
더 어리석은 방법은 힙이 빌드 된 후 차례로 힙을 출력하는 것입니다.
알고리즘 2
첫 번째 배열
알고리즘 2는 가장 작은 힙으로 조정하는 것이 아니라 가장 큰 힙
으로 조정하는 것입니다. 각 하위 트리는 차례로 조정됩니다. 조정 후 :
작은 것에서 큰 것으로 정렬되기 때문에 가장 큰 d는 마지막 노드와 교환되어야합니다. 즉,
아래에 배치 한 후 d가 최종 위치에 배치되었으므로 힙의 전체 크기를 1 (d 제외) 줄이고 d가
아닌 힙을 가장 큰 힙으로 조정
하고 c와 마지막 힙의 노드 (즉, a) 교환하고 c를 잘라낸
다음 a와 b를 가장 큰 더미로 조정 한
다음 교환을합니다.
마지막으로 더미 분류가 완료됩니다.
더미를 학습하면 a [ 0]은 요소에 배치되지 않지만 센티널은 배치됩니다. 그러나 정렬 할 때 a [0]은 요소
PercDown (A, i, N)을 배치합니다. 하위 기능을 필터링하고 i는 루트 노드에 해당하는 위치입니다. .
질문 2는 알고리즘 2 여야합니다 . 먼저 가장 큰 힙으로 조정하십시오.
4 병합 정렬
4.1 정렬 된 하위 열 병합
여기서 포인터 (Aptr \ Bptr \ Cptr)는 배열의 위치를 나타냅니다.
A가 가리키는 값과 B가 가리키는 숫자를 비교합니다.
각 요소는 한 번만 스캔되고 시간 복잡도는 분명히 O (N)
A입니다. [] : 두 개의 배열을 포함합니다. 왼쪽은 첫 번째, 오른쪽은 두 번째, 두 개의 배열은
마지막 단계 옆에 저장 되고 정렬 된 배열 TmpA []는 A []에 다시 저장되어야하지만 L은 더 이상 없습니다. 참조 A []가 시작되었지만 RightEnd가 움직이지 않았으므로 뒤에서 앞으로 저장하십시오.
4.2 재귀 알고리즘
최고, 최악, 평균 시간 복잡성은 없습니다
.Merge_sort ()에서 TmpA를 선언하는 것이 좋습니다 .Merge 함수에서 TmpA를 사용하는 것이 좋은 이유는 무엇
입니까?
사전 선언 :
위의 첫 번째 단락을 정렬 할 때 아래의 녹색 부분을 사용하여 병합 한 다음 녹색 부분을 다시 맨 위로 가져옵니다
. 아래 Tmp 배열의 공간은 반복적으로 사용
되지만 그렇지 않은 경우 미리 선언하십시오 :
많은 malloc을 수행하고 무료
이므로 먼저 배열을 연 다음 더 비용 효율적일 때마다 포인터를 전달하는 것이 좋습니다
4.3 비 재귀 알고리즘
재귀는 시스템의 스택을 사용하며 재귀를 느리게 만드는 많은 추가 작업이
있습니다. 가장 큰 시퀀스
가 합성 될 때까지 인접한 두 개의 작업이 하위 시퀀스로 결합됩니다.
가장 작은 것을 달성하기 위해 많은 공간 (로그온 계층)을 사용할 수 있습니다. 두 가지 추가 공간 복잡성은 O (N)이며
임시 배열 만 열면됩니다. A를 임시 배열에 병합하고 다음에 임시 배열을 A에 병합합니다. . . 마지막 단계는 A에 있거나 임시 배열의
for 루프 에 있는 두 번째 하위 시퀀스 쌍 으로 병합 될 수 있으므로 i <= N-2 길이
의 마지막
쌍의 가능한 수는 이전 것이므로 특별한 처리가 필요하므로 Merge ()는 결국 Tmp 배열을 A로 되돌 리지만 여기에서는 사용되지 않으므로 Merge1 Merge1 (A, TmpA, i, i + length, i + 2 length-1)을 사용하십시오. :
- i : 첫 번째 단락의 시작 위치
- i + length : 두 번째 단락의 시작 위치
- i + 2 * lenght-1 : 두 번째 단락의 끝 위치
병합 정렬의 최고 및 최악의 시간 복잡성은 O (nlogn)
이지만 추가 공간이 필요합니다.
모든 데이터는 메모리에 있으며 병합 할 필요가 없습니다
. 병합은 외부 정렬에 유용합니다.
5 빠른 정렬
5.1 알고리즘 개요
가장 빠른 알고리즘이지만 여전히 최악의 경우가 있습니다. 직접 작성하면 일부 세부 사항이 제대로 구현되지 않으면 알고리즘이 더 이상 빠른 정렬
및 병합이 되지 않도록하기 쉽습니다 . 둘 다 나누기 및 정복을 사용
하여 피벗 을 선택하고, 어느 쪽이 더
큽니까? 오른쪽에, 작은 쪽을 왼쪽에 놓고 정렬 합니다. 재귀는 언제 끝나나요? 요소가 하나만 있으면 증명이 끝납니다
질문 :
1. 주요소 선택
방법 2. 부분 집합 분할 방법
이 두 문제가 잘 해결되지 않으면 빠른 정렬이 빠르지 않습니다.
5.2 피벗 선택
가장 왼쪽과 가운데 세 숫자의 중앙값이 사용됩니다. 세 숫자가 교환 된 후 가장 왼쪽 저장소는 세 숫자 중 최소값이고 가장 오른쪽 저장소는 세 개의 빗질 된 최대 값입니다. 그리고 가장 오른쪽의 숫자가 나뉘 었습니다. 그런 다음 중간 숫자 (예 : a [center])를 a [right-1]에 넣어이 3 개의 숫자를 덜 고려하고 a [left + 1] -a [right-2] 만 처리합니다.
5.3 부분 집합 분할
다음은 a [left + 1] -a [right-2]
빨간색 6이 선택된 피벗입니다.
목표는 왼쪽 요소를 <6, 오른쪽 요소를> 6으로 만드는 것입니다.
i가 <6을 가리키는 경우 , 포인터가 뒤로 이동
하고 j가 6보다 크면 포인터가 앞으로 이동 합니다 .i가> 6을 가리키고 j가 <6을 가리키고있는 경우 값에 대한 두 지점이
그림과 같이 바뀝니다. . 다음 아래 그림 그것은된다 :
교환 한 후,이 시간> 6에서 지점까지 9 전진,
이번에 <6에서, J 이동하고 J 가리키는까지 전진하기 시작한다.
환 이러한 두 가지 요소
. 빠른 정렬이 빠른 이유는 무엇입니까? 피벗 을 한 번에 최종 위치에두기 때문에 앞으로는 움직이지 않을 것입니다.
삽입 정렬과 달리 위치는 일시적 일뿐입니다.
피벗과 같은 요소가 있으면 어떨까요?
- 교환을 중지 하시겠습니까?
- 무시하고 포인터를 계속 이동 하시겠습니까?
극단적 인 경우를 고려하면 배열의 값이 모두 동일합니다.
- 교환을 중단하면이 숫자들은 의미없는 교환을 많이 할 것입니다. 하나의 장점은 반복적으로 2 개의 시퀀스로 나눌 때마다 복잡성이 nlogn이라는 것입니다.
- 그를 무시하면 나는 오른쪽 끝까지 움직일 것이고 j는 움직일 기회가 없기 때문에 피벗은 끝점에 놓이게 될 것이다. 그래서 이것은 매우 부끄러운 상황이고 시간 복잡도는 N 2 가 될 것이다.
- 그래서 멈추고 교환하는 것이 낫습니다.
5.4 알고리즘 구현
요소가 피벗과 정확히 일치하면 교환되어 불안정해질 수 있습니다.
6 테이블 정렬
6.1 알고리즘 개요
정렬 하고자하는 것이 요소가 아니라 구조라면이 구조를 이동하는 시간은 무시할 수 없습니다.
위의 알고리즘은 반드시 교환해야합니다.
테이블 정렬을 사용하고 포인터를 움직여
키 를 비교하고 전체를 교환하지 마십시오. 그러나 테이블 교환 만 포인터
삽입 정렬을 사용하면 테이블의 값은 다음과 같습니다.
6.2 물리적 주문
정렬해야하는 구조
변경 후 테이블 값에 따라
table [0] = 3과 같은 여러 개의 링을 결정한 다음 table [3]의 값을 테이블 [3] = 1에 넣은 다음 테이블 [1]의 값을 링에 넣습니다. . .
2 개의 숫자를 이동하려면 3 단계가 필요하므로 시간이 더 걸립니다.
7 카디널리티 정렬
7.1 버킷 정렬
N은 학생 점수를 삽입하는 데 필요하고 M은 출력 할 때 모든 버킷을 스캔하는 데 필요합니다.
7.2 카디널리티 정렬
총 P 개의 패스가 실행되고 N 개의 요소가 각 패스에 할당되며 B 개의 버킷이 방문됩니다.
7.3 여러 키워드로 정렬
카드 놀이에 관한 한 두 번째 우선 순위는 주요 우선 순위보다 더 똑똑합니다.
8 정렬 알고리즘 비교
선택적 정렬은 정렬이기 때문에 불안정,
버블 링, 직접 삽입은 인접한 두 개의 교환기이므로 안정적이므로 별도의 공간이 필요하지 않습니다
. 2. 삽입은 직접 제외, 역순이면 삽입 정렬, 마지막 전 마지막으로 삽입 된 숫자가 가장 작기 때문에 요소가 마지막 위치에 있으면 안되며, 첫 번째 숫자로 이동해야하며 다른 숫자는 뒤로 이동해야합니다
. 기본적으로 질서
정렬 효율성은 나쁘지 않을 것 입니다 4. Bubbling : 2 정렬 후 3 개 불가, 2 개
삽입 : 2 개 삽입 후 2, 3 개
선택 : 첫 번째 숫자는 가장 작은 값이어야 함
선택 정렬 및 힙 정렬은 다음과 같습니다. OK 당신은 후 상위 10 번호를 얻기 위해 그들 모두를 정렬 할 필요가 없습니다
. 정렬하지만, 정렬 선택하려면 시간이 많이 걸리는 가장 큰 값을 찾기 위해 모든 숫자를 통과해야하는
(그리고 코드의 안식처 ' 작성되었습니다)