一、简单选择排序
设所排序序列的记录个数为n。i取1,2,...,n-1,从所有n-i+1个记录中找出排序码最小的记录,与第i个记录交换。执行n-1趟后就完成了记录序列的排序。
最好时间复杂度:O(n^2), 平均时间复杂度:O(n^2), 最坏时间复杂度:O(n^2) 辅助存储:O(1) 不稳定
public class SelectionSort {
public int[] selectionSort(int[] A, int n) {
int position = 0;
for(int i=0;i<n;i++){
int minStemp=java.lang.Integer.MAX_VALUE;
for(int j=i;j<n;j++){
if(A[j]<minStemp){
minStemp = A[j];
position = j;
}
}
int temp = A[i];
A[i] = minStemp;
A[position] = temp;
}
return A;
}
}
二、直接插入排序
每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
最好时间复杂度:O(n), 平均时间复杂度:O(n^2), 最坏时间复杂度:O(n^2) 辅助存储:O(1) 稳定
public class InsertionSort {
public int[] insertionSort(int[] A, int n) {
int j=0;
for(int i=0;i<n;i++){
int temp = A[i];
for(j=i;j>0&&A[j-1]>temp;j--){
A[j]=A[j-1];
}
A[j]=temp;
}
return A;
}
}
三、冒泡排序
比较相邻的元素,如果第一个比第二个大,就交换他们两个。对每一对相邻的元素作同样的工作,从开始第一对到结尾的最后一对,最后的元素应该是最大的数。
最好时间复杂度:O(n), 平均时间复杂度:O(n^2), 最坏时间复杂度:O(n^2) 辅助存储:O(1) 稳定
public class BubbleSort {
public int[] bubbleSort(int[] A, int n) {
int temp;
for(int i=0;i<n-1;i++){
for(int j=0;j<n-i-1;j++){
if(A[j]>A[j+1]){
temp = A[j+1];
A[j+1] = A[j];
A[j] = temp;
}
}
}
return A;
}
}
四、希尔排序
它是直接插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效地改进版本。
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组,所有距离为d1的倍数的记录放在同一个组中。现在各组内进行直接插入排序;然后,取第二个增量d2<d1,重复上述的分组和排序,直至所取的增量dt=1,即所有记录放在同一组中进行直接插入排序为止。
最好时间复杂度:O(n), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n*s) s为所选分组 辅助存储:O(1) 不稳定
public class ShellSort {
public int[] shellSort(int[] A, int n) {
if(A==null || n<2)
return A;
int feet = n/2;
int index = 0;
while(feet > 0){
for(int i=feet; i<n; i++){
index = i;
while(index >= feet){
if(A[index-feet] > A[index]){
swap(A,index-feet,index);
index-=feet;
}else{
break;
}
}
}
feet = feet/2;
}
return A;
}
void swap(int[] A,int m,int n){
int temp = A[m];
A[m] = A[n];
A[n] = temp;
}
}
五、快速排序
它是对冒泡排序的一种改进。
基本思想:通过一趟排序将要排序的部分分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按照此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
最好时间复杂度:O(n*logn), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n^2) 辅助存储:O(logn) 不稳定
public class QuickSort {
public static int[] quickSort(int[] A, int n) {
quick(A, 0, n - 1);
return A;
}
private static int[] quick(int[] A, int low, int high) {
if (low < high) {
int mid = sort(A, low, high);
quick(A, low, mid-1);
quick(A, mid + 1, high);
}
return A;
}
private static int sort(int[] A, int low, int high) {
int key = A[low];
int i = low;
int j = high;
if (low < high) {
while (i < j) {
while (i < j && key <= A[j]) {
j--;
}
if (i < j) {
A[i] = A[j];
}
while (i < j && A[i] <= key) {
i++;
}
if (i < j) {
A[j] = A[i];
}
}
A[i] = key;
}
return i;
}
}
六、堆排序
用大根堆排序的基本思想:
1)先将初始文件R[1,...,n]建成一个大根堆,此堆为初始的无序区。
2)再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1,...,n-1]和有序区R[n],且满足R[1,...,n-1].keys<=R[n].key。
3)由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1,...,n-1]调整为堆。然后再次将R[1,...,n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1,...,n-2]和有序区R[n-1,n],且仍满足关系R[1,...,n-2].keys<=R[n-1,n].keys。同样要将R[1,...,n-2]调整为堆。
......
直到无序区只有一个元素位置。
最好时间复杂度:O(n*logn), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n*logn) 辅助存储:O(1) 不稳定
public class HeapSort {
public int[] heapSort(int[] A, int n) {
for(int i=n/2; i>=0; i--){
heapAdjust(A,i,n);
}
for(int i=n-1;i>0;i--){
swap(A,0,i);
heapAdjust(A,0,i);
}
return A;
}
public void heapAdjust(int[] A,int index,int length){
int childLeft;
int temp = A[index];
for( ;index*2+1 < length;index = childLeft){
childLeft = index*2+1;
if(childLeft !=length-1 && A[childLeft] < A[childLeft+1]){
childLeft++;
}
if(temp > A[childLeft]){
break;
}
else {
A[index] = A[childLeft];
index = childLeft;
}
}
A[index] = temp;
}
public static void swap(int[] A,int m,int n){
int temp = A[m];
A[m] = A[n];
A[n] = temp;
}
}
七、归并排序
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,成为二路归并。
归并排序的算法通常用递归实现,先把待排区间[s,t]以中点二分,接着把左边自区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
最好时间复杂度:O(n*logn), 平均时间复杂度:O(n*logn), 最坏时间复杂度:O(n*logn) 辅助存储:O(n) 稳定
public class MergeSort {
public int[] mergeSort(int[] A, int n) {
sort(A,0,n-1);
return A;
}
public void sort(int[] data,int left,int right){
if(left<right){
int middle = (left+right)/2;
sort(data,left,middle);
sort(data,middle+1,right);
merge(data,left,middle,right);
}
}
public void merge(int[] data,int left,int middle,int right){
int[] tempArr = new int [right-left+1];
int leftIndex = left;
int rightIndex = middle+1;
int tempIndex = 0;
while(leftIndex<=middle && rightIndex<=right){
if(data[leftIndex]<=data[rightIndex]){
tempArr[tempIndex++] = data[leftIndex++];
} else {
tempArr[tempIndex++] = data[rightIndex++];
}
}
while(leftIndex<=middle){
tempArr[tempIndex++] = data[leftIndex++];
}
while(rightIndex<=right){
tempArr[tempIndex++] = data[rightIndex++];
}
int temp = 0;
while((temp+left)<=right){
data[left+temp] = tempArr[temp];
temp++;
}
}
}