1. 选择排序
1.1 简单选择排序
简单选择排序的思想是:在数组r[1…n]中,第一趟从r[1]开始,进行n-1次比较,找出关键字最小的记录,与r[1]进行交换,第二趟从r[2]开始,进行n-2次比较,在剩余记录中找出关键字最小的记录,以此类推,经过n-1趟,排序完成。该排序方法主要通过多次遍历数组,每次遍历数组时将所遍历到的最小数据与未排序数据最左端交换,最终使得数组正序。以下是简单选择排序的java实现:
/**
*
* 直接选择排序
* 时间复杂度O(n²)
* 空间复杂度O(1)
* 可用于链式存储结构
* 不稳定排序
* 移动记录次数较少
* 每一记录占用的空间较多时优于直接插入排序
*
*/
private static void directSelectionSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int k = i;
for (int j = i+1; j < array.length; j++) {
if(array[j] < array[k]) {
k = j;
}
}
if(k!=i) {
int tmp = array[i];
array[i] = array[k];
array[k] = tmp;
}
}
printArray(array);
}
1.2 简单选择排序
堆排序算法的主要思想就是,将无需序列建成初堆以后,反复将堆的根结点与堆的最后一个结点交换,然后再将除最后一个结点的树重新调整为堆,经过多次调整后,由于堆的性质(堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。 根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆。)最后该堆能够变成有序状态。堆排序经历三个主要过程:
1)建初堆
从i=n/2(即最后一个有子节点的节点)开始,将i减小,反复使用筛选法,依次将以r[i]为根的子树调整为堆,通过对每一个子树变为堆达到整棵树变成堆的目的。
2)调整堆
调整堆的过程作用于该结点以及该结点的所有子孙结点。沿着key较大的孩子结点向下筛选,将每一个结点及其所有子孙节点通过两两比较进行交换的方式调整为堆。
3)堆排序
堆排序的过程是将前面两个过程进行整合,先进行建初堆,然后通过循环将堆的根结点与未排序的最后一个结点进行交换,然后再从树的根部开始,对整颗未排序的树进行堆调整,如此循环,最后使得堆达到有序。以下是堆排序的java实现:
/**
*
* 堆排序
* 时间复杂度O(nlong2n)
* 空间复杂度O(1)
* 只能用于顺序结构
* 不稳定排序
* 记录多时为高效
*
*/
private static void heapSort(int[] array) {
CreateHeap(array);
for (int i = array.length-1; i > 0; i--) {
int tmp = array[0];
array[0] = array[i];
array[i] = tmp;
HeapAdjust(array, 0, i-1);
}
printArray(array);
}
//调整成大根堆
private static void HeapAdjust(int[] array, int s, int m) {
int root = array[s];
for (int i = 2*s+1; i <= m; i= 2*i+1) {
if(i<m&&array[i]<array[i+1])
i++;
if(root>=array[i])
break;
array[s] = array[i];
s = i;
}
array[s] = root;
}
//把array建成大根堆
private static void CreateHeap(int[] array) {
int n = array.length - 1;
for (int i = n/2; i >= 0; i--) {
HeapAdjust(array, i, n);
}
}
2. 归并排序
归并排序的算法思想是:将当前通过递归方法循环地一分为二,直至序列被分为若干个只含一条数据的表,然后再将相邻表两两合并。合并方法为:每次分别从两个表中取出一个记录进行关键字的比较,将较小着放入T中,重复此过程,直至其中一个表为空,最后将另一非空表中余下的部分直接复制到T中。即两个相邻表的数据存放在同一个数组中的不同初始下标内,每次合并的时候将这两个相邻表合并后,重新组合其在数组中的位置。以下是归并排序的java实现:
/**
*
* 归并排序
* 时间复杂度O(nlong2n)
* 空间复杂度O(n)
* 可用于链式结构
* 稳定排序
*
*/
private static void mergeSort(int[] array) {
Msort(array, array, 0, array.length-1);
printArray(array);
}
private static void Msort(int[] R, int[] T, int low, int high) {
int[] S = new int[R.length];
if(low == high)
T[low] = R[low];
else {
int mid = (low + high) / 2;
Msort(R, S, low, mid);
Msort(R, S, mid+1, high);
Merge(S, T, low, mid, high);
}
}
private static void Merge(int[] R, int[] T, int low, int mid, int high) {
int i = low;
int j = mid + 1;
int k = low;
while (i<=mid&&j<=high) {
if(R[i]<=R[j])
T[k++] = R[i++];
else
T[k++] = R[j++];
}
while (i<=mid)
T[k++] = R[i++];
while (j<=high)
T[k++] = R[j++];
}
3. 基本排序算法java实现汇总
public class Sort {
public static void main(String[] args) {
int[] array = {49, 38, 65, 97, 76, 13, 27, 49};
/**
* InsertSort
*/
// directInsertSort(array);
// binaryInsertSort(array);
// ShellSort(array);
/**
* ExchangeSort
*/
bubbleSort(array);
// quickSort(array);
/**
* SelectSort
*/
// directSelectionSort(array);
// heapSort(array);
/**
* MergeSort
*/
// mergeSort(array);
}
/**
*
* 归并排序
* 时间复杂度O(nlong2n)
* 空间复杂度O(n)
* 可用于链式结构
* 稳定排序
*
*/
private static void mergeSort(int[] array) {
Msort(array, array, 0, array.length-1);
printArray(array);
}
private static void Msort(int[] R, int[] T, int low, int high) {
int[] S = new int[R.length];
if(low == high)
T[low] = R[low];
else {
int mid = (low + high) / 2;
Msort(R, S, low, mid);
Msort(R, S, mid+1, high);
Merge(S, T, low, mid, high);
}
}
private static void Merge(int[] R, int[] T, int low, int mid, int high) {
int i = low;
int j = mid + 1;
int k = low;
while (i<=mid&&j<=high) {
if(R[i]<=R[j])
T[k++] = R[i++];
else
T[k++] = R[j++];
}
while (i<=mid)
T[k++] = R[i++];
while (j<=high)
T[k++] = R[j++];
}
/**
*
* 堆排序
* 时间复杂度O(nlong2n)
* 空间复杂度O(1)
* 只能用于顺序结构
* 不稳定排序
* 记录多时为高效
*
*/
private static void heapSort(int[] array) {
CreateHeap(array);
for (int i = array.length-1; i > 0; i--) {
int tmp = array[0];
array[0] = array[i];
array[i] = tmp;
HeapAdjust(array, 0, i-1);
}
printArray(array);
}
//调整成大根堆
private static void HeapAdjust(int[] array, int s, int m) {
int root = array[s];
for (int i = 2*s+1; i <= m; i= 2*i+1) {
if(i<m&&array[i]<array[i+1])
i++;
if(root>=array[i])
break;
array[s] = array[i];
s = i;
}
array[s] = root;
}
//把array建成大根堆
private static void CreateHeap(int[] array) {
int n = array.length - 1;
for (int i = n/2; i >= 0; i--) {
HeapAdjust(array, i, n);
}
}
/**
*
* 直接选择排序
* 时间复杂度O(n²)
* 空间复杂度O(1)
* 可用于链式存储结构
* 不稳定排序
* 移动记录次数较少
* 每一记录占用的空间较多时优于直接插入排序
*
*/
private static void directSelectionSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int k = i;
for (int j = i+1; j < array.length; j++) {
if(array[j] < array[k]) {
k = j;
}
}
if(k!=i) {
int tmp = array[i];
array[i] = array[k];
array[k] = tmp;
}
}
printArray(array);
}
/**
*
* 快速排序
* 时间复杂度O(nlog2n)
* 空间复杂度最好O(log2n)最差O(n)
* 需要定位表的上界和下界适合顺序结构
* 不稳定排序
* 平均情况是所有内部排序方法中速度最快的一种
*
*/
private static void quickSort(int[] array) {
qSort(array, 0, array.length-1);
printArray(array);
}
private static void qSort(int[] array, int low, int high) {
if(low < high) {
int index = Partition(array, low, high);
qSort(array, low, index-1);
qSort(array, index+1, high);
}
}
private static int Partition(int[] array, int low, int high) {
int tmp = array[low];
while (low < high) {
while (low<high && array[high]>=tmp) {
high--;
}
array[low] = array[high];
while (low<high && array[low]<=tmp) {
low++;
}
array[high] = array[low];
}
array[low] = tmp;
return low;
}
/**
*
* 冒泡排序
* 时间复杂度O(n²)
* 空间复杂度O(1)
* 可用于链式存储结构
* 稳定排序
* 平均时间性能比直接插入排序差
*
*/
private static void bubbleSort(int[] array) {
int flag = 1;
for (int i = array.length - 1; i > 0 && flag == 1; i--) {
flag = 0;
for (int j = 0; j < i; j++) {
if(array[j] > array[j+1]) {
flag = 1;
int tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
}
}
}
printArray(array);
}
/**
*
* 希尔排序
* 时间复杂度O(n的1.3次方)
* 空间复杂度O(1)
* 记录跳跃式移动导致不稳定排序
* 适合初始记录无序、n较大的情况
*
*/
private static void ShellSort(int[] array) {
//定义增量数组
int dt[] = {5, 3, 1};
for (int i = 0; i < dt.length; i++) {
ShellInsert(array, dt[i]);
}
printArray(array);
}
private static void ShellInsert(int[] array, int t) {
for (int i = t; i < array.length; i++) {
if(array[i] < array[i-t]) {
int tmp = array[i];
int j;
for (j = i-t; (j>=0)&&(tmp < array[j]); j -= t) {
array[j+t] = array[j];
}
array[j+t] = tmp;
}
}
}
/**
*
* 折半插入排序
* 时间复杂度O(n²)
* 空间复杂度O(1)
* 稳定排序
* 适合初始记录无序、n较大的情况
*
*/
private static void binaryInsertSort(int[] array) {
for (int i = 1; i < array.length; i++) {
int temp = array[i];
int low = 0;
int high = array.length-1;
while (low <= high) {
int m = (low + high) / 2;
if(temp < array[m]) {
high = m - 1;
}
else {
low = m + 1;
}
}
int j;
for (j = i-1; j >= high+1;) {
array[j+1] = array[j];
j--;
if (j<0) {
break;
}
}
array[j+1] = temp;
}
printArray(array);
}
/**
*
* 直接插入排序
* 时间复杂度O(n²)
* 空间复杂度O(1)
* 稳定排序
* 适合基本有序情况
*
*/
private static void directInsertSort(int[] array) {
for (int i = 1; i < array.length; i++) {
if(array[i] < array[i-1]) {
int temp = array[i];
int j;
for (j = i-1; (j>=0)&&(temp < array[j]); j--) {
array[j+1] = array[j];
}
array[j+1] = temp;
}
}
printArray(array);
}
private static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
}