오랜만이다~
콘텐츠
1. 개념
정렬은 하나 또는 일부 키워드의 크기에 따라 일련의 레코드를 오름차순 또는 내림차순으로 정렬하는 작업입니다. 일반적인 컨텍스트에서 정렬이 언급되면 일반적으로 오름차순을 나타냅니다. 일반적인 의미의 정렬은 제자리 정렬을 의미합니다.
1.1 안정성
두 개의 동일한 데이터, 정렬 알고리즘이 정렬 후 상대 위치가 변경되지 않도록 할 수 있는 경우 알고리즘을 안정적인 정렬 알고리즘이라고 합니다. (즉, 동일한 요소의 상대 위치가 변경되기 전 요소의 순서와 상대 위치 변경 후 요소의 순서가 일관되어야 함)
불안정한 정렬로 구현할 수 있는 안정적인 정렬 그러나 본질적으로 불안정한 정렬은 안정적인 정렬이 될 수 없습니다. 아래 그림과 같이 :
2. 7대 랭킹
2.1 삽입 정렬
2.1.1 직접 삽입 정렬 - 원리
원칙:전체 간격은 정렬된 간격, 정렬되지 않은 간격으로 나뉩니다.매번 순서가 없는 구간의 첫 번째 요소를 선택하고 삽입할 정렬된 간격에서 적절한 위치를 선택합니다.문제 해결 아이디어:① 임시 저장 지점 tmp를 찾아 각 정렬되지 않은 간격에 아래 첨자 i가 표시된 첫 번째 요소를 넣습니다.② 다른 변수 j를 사용하여 tmp가 나타내는 요소의 크기를 판단합니다.③ 종료 루프 조건을 j<0이 될 때까지 설정코드 쇼는 아래와 같습니다.
public static void insertSort(int[] array) {
for (int i = 1; i < array.length; i++) {
int tmp = array[i];
int j = i-1;
for (; j >= 0 ; j--) {
if(array[j] > tmp) {
array[j+1] = array[j];
}else {
//array[j+1] = tmp; 只要j回退的时候,遇到了 比tmp小的元素就结束这次的比较
break;
}
}
//j回退到了 小于0 的地方
array[j+1] = tmp;
}
}
2.1.2 성능 분석
최대 평균 가장 나쁜 시간 복잡도 켜짐) 오(N²) 오(N²) 공간 복잡도 오(1) 오(1) 오(1) 안정 안정화 안정화 안정화
2.1.3 반접기 삽입 정렬(이해)
원칙:
반 검색의 아이디어를 사용하여 정렬
문제 해결 아이디어:
① 각 루프에 대해 왼쪽 값을 0으로, 오른쪽 값을 i로 설정합니다.
② 둘의 중간에 좌표가 나타내는 값과 판단할 값의 관계를 판단하기 위해 타협
③array[mid]<판정값이면 left=mid+1, 그렇지 않으면 array[mid]>판정값 right=mid (배열[mid]보다 큰 값을 찾아 교환하기 위함)
코드 쇼는 아래와 같습니다.
public static void bsInsertSort(int[] array) { for (int i = 1; i < array.length; i++) { int v = array[i]; int left = 0; int right = i; // [left, right) // 需要考虑稳定性 while (left < right) { int m = (left + right) / 2; if (v > array[m]) { left = m + 1; } else { right = m-1; } } // 搬移 for (int j = i; j > left; j--) { array[j] = array[j - 1]; } array[left]=v; } }
2.2 힐 정렬
2.2.1 원칙
원칙:힐 소팅 방법은 수축 증분 방법으로도 알려져 있습니다. 힐 정렬 방법의 기본 아이디어는 먼저 정수를 선택하고 정렬할 파일의 모든 레코드를 그룹으로 나누고 정렬할 파일의 모든 레코드를 그룹으로 나누는 것입니다.거리가 인 레코드를 동일한 그룹으로 그룹화하고 각 그룹 내의 레코드를 정렬합니다. 그런 다음 위의 그룹화 및 정렬 작업을 반복하십시오. =1 에 도달하면 모든 레코드가 통합 그룹 내에서 정렬됩니다.1. 힐 정렬은 직접 삽입 정렬의 최적화입니다.2. gap > 1 일 때 사전 정렬되며 목적은 배열을 순서에 더 가깝게 만드는 것입니다. gap == 1이면 배열이 이미 정렬에 가깝기 때문에 빠릅니다. 이러한 방식으로 최적화의 전반적인 효과를 얻을 수 있습니다.문제 해결 아이디어: (본체는 그것을 여러 부분으로 나누고 각 부분은 자체 재귀를 수행합니다)
① 증분값을 구하는 문제는 특정 문제를 풀 때 소수인지 확인하기가 쉽지 않아 종종 gap/=2의 방식으로 푸는 경우가 많다.
②실제로는 삽입정렬이지만 직접정렬에서 j=i-1의 첨자값을 j=i-gap으로 대체한다.
코드 쇼는 아래와 같습니다.
public static void shell(int[] array,int gap) { for (int i = gap; i < array.length; i++ ) { int tmp = array[i]; int j = i-gap; for (; j >= 0 ; j -= gap) { if(array[j] > tmp) { array[j+gap] = array[j]; }else { break; } } array[j+gap] = tmp; } } public static void shellSort(int[] array) { int gap = array.length; while (gap > 1) { shell(array,gap); gap /= 2; } shell(array,1);//保证最后是1组 }
2.2.2 성능 분석
유형 해당 매개변수 시간 복잡도 O(N의 1.3제곱 ~ N의 1.5제곱) 공간 복잡도 오(1) 안정 불안정한
2.3 선택 정렬
2.3.1 원칙
원칙:매번 무순 간격에서 가장 큰(또는 가장 작은) 요소를 선택하고 정렬할 데이터 요소가 모두 소진될 때까지 무순 간격의 끝(또는 앞)에 저장합니다.문제 해결 아이디어:① 사실 쌍의 크기를 비교하여 교환하고, 최종적으로는 순서열이 되는 과정이다.②최적화된 코드는 실제로 매번 최소값의 첨자를 직접 찾아 i값의 첨자와 직접 교환코드 분석:public static void swap(int a,int b){ int tmp=a; a=b; b=tmp; } //选择排序:不稳定的排序 public static void selectSort(int []array){ for(int i=0;i<array.length;i++){ for(int j=i+1;j<array.length;j++){ if(array[i]>array[j]){ swap(array[i],array[j]); } } } }//以下为优化好后的代码,此处的优化,指的是交换次数的变化,而时间复杂度并为更改 public static void selectSort1(int []array){ for(int i=0;i<array.length;i++){ //将最小值的下标记录下来,而i在交换中只需要与这个最小值进行比较 int minSize=i; for(int j=i+1;j<array.length;j++){ if(array[j]<array[minSize]){ minSize=j; } }swap(array[i],array[minSize]); }
2.3.2 성능 분석
유형 해당 매개변수 시간 복잡도 오(N²) 공간 복잡도 오(1) 안정 불안정한
2.4 힙 정렬(힙에 대한 이전 섹션에서 자세히 설명)
2.4.1 원칙
원칙:기본 원칙도 선택 정렬이지만 순회를 사용하여 정렬되지 않은 간격의 가장 큰 수를 찾는 대신 힙을 사용하여 정렬되지 않은 간격의 가장 큰 수를 선택합니다.문제 해결 아이디어:① 힙 빌드(큰 루트 힙 빌드)② 아래로 스왑하여 조정코드 쇼는 아래와 같습니다.public static void heapSort(int []array){ createHeap(array); int end=array.length-1; while(end>0){ swap(array[0],array[end]); shiftDown(array,0,end); end--; } } public static void createHeap(int[]array){ for(int parent=(array.length-1-1)/2;parent>=0;parent--){ shiftDown(array,parent,array.length); } }//向下调整 public static void shiftDown(int[]array,int parent,int len){ int child=2*parent+1;//左孩子下标 while(child<len){ if(child+1<len && array[child]<array[child+1]){ child++;//保证下标为较大值的下标 } if(array[child]>array[parent]){ swap(array[child],array[parent]); parent=child; child=2*parent+1; }else{ break; } } }
2.4.2 성능 분석
유형 해당 매개변수 시간 복잡도 O(N * 로그 N) 공간 복잡도 오(1) 안정 불안정한
2.5 버블 정렬
2.5.1 원칙
원칙:무순구간에서는 인접한 수의 비교를 통해 무순구간이 끝날 때까지 가장 큰 수를 버블링하며, 이 과정은 배열이 전체적으로 정렬될 때까지 계속된다.문제 해결 아이디어:① j를 사용하여 각 이동의 크기를 비교하고 가장 큰 것은 각 이동이 끝날 때 바닥으로 가라앉습니다.②i를 사용하여 패스 수를 나타냅니다.③ 최적화된 코드에 flg=false를 추가하여 교환이 없도록 하고 루프에서 직접 점프하여 시간을 절약합니다.코드 분석://冒泡排序(稳定的排序。时间复杂度为n²,在排好序的情况下时间复杂度为n,空间复杂度为O(1) public static void bubblesort(int array[]){ boolean flg=false; for (int i = 0; i < array.length-1; i++) { for(int j=0;j<array.length-1-i;j++){ if(array[j]>array[j+1]){ swap(array[j],array[j+1]); flg=true; } } if(flg=false){ break; } } }
2.5.2 성능 분석
유형 해당 매개변수 시간 복잡도 오(N²) 공간 복잡도 오(1) 안정 안정화
2.6 빠른 정렬(중요)
2.6.1 원칙
원칙:1. 범위에서 피벗 값 으로 정렬할 숫자를 선택합니다 .2. 파티션: 정렬할 전체 구간을 순회하고, 기준 값보다 작은 값(같음을 포함할 수 있음)을 기준 값의 왼쪽에 놓고 기준 값보다 큰 값(같음을 포함할 수 있음)을 다음 위치에 넣습니다. 참조 값의 오른쪽;3. 분할과 정복의 개념을 채택하고, 왼쪽과 오른쪽 셀을 같은 방식으로 처리합니다. 셀의 길이 == 1 , 즉 순서가 지정되었음을 의미하거나 셀의 길이 == 0이 될 때까지 , 이는 데이터가 없음을 의미합니다.문제 해결 아이디어:①기준점을 찾아 기준점을 구분선으로 하여 기준점 왼쪽의 값이 기준점보다 크면 오른쪽 빈 공간으로 전환하고 기준치보다 작으면 ++ 시작, 값이면 시작 벤치마크의 오른쪽이 벤치마크보다 작으면 왼쪽의 빈 위치로 전환합니다. end--;②파트별로 재귀적코드는 다음과 같습니다 1: (여기에 파기 방법이 있습니다)//快速排序 public static void quickSort(int []array){ quick(array,0,array.length-1); } public static void quick(int []array,int left,int right){ if(left>=right){ return ; }//找基准 int pivot=patition(array,left,right); //递归左边的 quick(array,left,pivot-1); //递归右边的 quick(array,pivot+1,right); } public static int patition(int []array,int start,int end) { int tmp = array[start]; while (start < end) { while (start < end && array[end] >= tmp) { end--; }//end下标遇到了小于tmp的值 array[start] = array[end]; while (start < end && array[start] <= tmp) { start++; }//start下标遇到了大于tmp的值 array[end] = array[start]; }//当start=end时 array[start]=tmp; return start; }
문제 해결 아이디어 2:
① 벤치마크 찾기
②데이텀을 찾은 후 데이텀의 양쪽에 굴착공법의 단계를 동시에 수행 ②양쪽에서 모두 큰 것과 작은 것이 발견되면 위치를 직접 교환
코드 2: (호레법)
private static int partition(int[] array, int left, int right) { int i = left; int j = right; int pivot = array[left]; while (i < j) { while (i < j && array[j] >= pivot) { j--; } while (i < j && array[i] <= pivot) { i++; } swap(array, i, j); } swap(array, i, left); return i; }
2.6.2 성능 분석
유형 해당 매개변수 시간 복잡도 O(K*N*logn)~O(N^2) 공간 복잡도 O(로그N) ~ O(N) 안정 불안정한
퀵 정렬 최적화에 대해, 그리고 나머지 병합 정렬은 다음 섹션에 나타납니다~~~