排序算法
一、 简单排序
1. 冒泡排序
(1)
(2)
a、相邻位置两两交换,直到最大数排好序。
b、对剩下元素重复此步骤。
code:
int temp; for(int i = arr.length - 1; i > 0; i--) for( int j = 0; j < i; i++) // 对 i 个元素,比较i - 1 次 if(arr[i] > arr[i + 1]){ temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; }
2. 选择排序
(1)
(2)
a、从队列中选择最小元素与队首元素交换,队首元素现已有序
b、重复步骤a
code:
for(int i = 0; i < arr.length - 1; i++){ int min = i; for(int j = i+1; j < arr.length; j++){ if(arr[min] > arr[j]) min = j; } swap(i, index); }
3. 插入排序
(1)
(2)
a、部分有序的数列,取出被标记元素,比该元素大的数依次右移。空处插入标记元素。
b、重复上步骤
code:
int i, j, temp; for( i = 1; i < arr.length; i++){ temp = a[i]; for( j = i; j > 0 && temp < arr[j-1]; j--) arr[j] = arr[j-1]; arr[j] = temp; }
二、 高级排序
1.归并排序
(1) (2) (3)
a、两个有序数组合并是简单的。
b、调用递归,将数组分成一半一半。
code:
public void merge(int[] workspace, int lowPtr, int highPtr, int upperBound){ int j = 0; int lowerBound = lowPtr; int mid = highPtr - 1; int n = upperBound - lowPtr + 1; while(lowPtr <= mid && highPtr <= upperBound) if(arr[lowPtr] < arr[highPtr]) workspace[j++] = arr[lowPtr++]; else workspace[j++] = arr[highPtr++]; while(lowPtr <= mid) workspace[j++] = arr[lowPtr++]; while(highPtr <= upperBound) workspace[j++] = arr[highPtr++]; for(j = 0; j < n; j++) arr[lowerBound + j] = workspace[j]; } public void recMergeSort(int[] workspace, int lowerBound, int upperBound){ if(lowerBound >= upperBound) return; int mid = (lowerBound + upperBound) / 2; recMergeSort(workspace, lowerBound, mid); recMergeSort(workspace, mid + 1, upperBound); merge(workspace, lowerBound, mid + 1, upperBound); }
2. 希尔排序
(1) (2)
a、对增量为N=(3*n + 1)的元素进行排序,N逐步减小直至为1.
b、当N为1时,该算法退化为插入排序。
code:
int inner, outer; int temp; int h = 1; while(h <= length/3) h = h*3 + 1; while(h>0){ for(outer = h; outer < length; outer++){ temp = arr[outer]; inner = outer; while(inner > h-1 && arr[inner-h] >= temp){ arr[inner] = arr[inner-h]; inner -= h; } arr[inner] = temp; } h = (h-1) / 3; }
3. 快速排序
a、以数组左右端元素为pivot划分数组
b、递归调用左右子数组
code:
public int partitionIt(int left, int right, int pivot){ int leftPtr = left - 1; int rightPtr = right; while(true){ while(leftPtr < right && arr[++leftPtr] < pivot) ; while(rightPtr > left && arr[--rightPtr] > pivot) ; if(leftPtr >= rightPtr) break; else swap(leftPtr, rightPtr); } swap(leftPtr, right); return leftPtr; } public void quickSort(int left, int right){ if(right <= left) return; else{ int pivot = arr[right]; int partion = partitionIt(left, right, pivot); quickSort(left, partion - 1); quickSort(partion + 1, right); } } }
4. 堆排序
堆排序分为建堆和堆调整两个过程。
首先描述堆调整过程,这是堆排序的核心。从最后一个非叶子节点开始。判断该节点与其最大子节点值的大小。若该节点值较小,则交换该节点与最大孩子节点。往下一直重复此操作,直至孩子节点<长度len为止。
对上一个非叶子节点重复操作,直至到达根节点为止。
public static void adjustHeap(int[] arr, int pos, int len){ int child; while(2*pos + 1 <= len){ // 判断是否到达最下层 child = 2*pos + 1; if(child < len && arr[child] < arr[child+1]) // 寻找最大子节点 child++; if(arr[pos] < arr[child]) swap(arr, pos, child); // 若父节点较小,交换 else break; pos = child; // 重置标志,往下重复到最下层 } }
public static void heapSort(int[] arr){ int len = arr.length; for(int i = len/2 - 1; i >= 0; i--) // 从最后一个非叶子节点开始,把堆调整为大根堆 adjustHeap(arr, i, len-1); //adjustHeap只调整一趟 for(int i = len-1; i >= 0; i--){ swap(arr, 0, i); adjustHeap(arr, 0, i-1); } }