关于常见的排序算法,《常用排序算法总结(一)》这篇文章写的很详细了,本文主要是把其中的算法用java语言实现一遍
1.冒泡排序
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j];
}
public static void bubbleSort(int[] arr) {
boolean didSwap;
for (int i = 0, len = arr.length; i < len - 1; i++) {
didSwap = false;
for (int j = 0; j < len - i - 1; j++) {
if (arr[j + 1] < arr[j]) {
swap(arr, j, j + 1);
didSwap = true;
}
}
//添加这一步,才能使排序最好O(n)
if (didSwap == false) {
return;
}
}
}
/**
* 鸡尾酒排序
* @param a
* @param n
*/
public static void cocktailSort(int[] a, int n) {
int left = 0; // 初始化边界
int right = n - 1;
while (left < right) {
for (int i = left; i < right; i++) // 前半轮,将最大元素放到后面
{
if (a[i] > a[i + 1]) {
swap(a, i, i + 1);
}
}
right--;
for (int i = right; i > left; i--) // 后半轮,将最小元素放到前面
{
if (a[i - 1] > a[i]) {
swap(a, i - 1, i);
}
}
left++;
}
}
2.选择排序
public static void selectSort(int[] a){
if(a == null || a.length < 2){
return;
}
for(int i = 0; i < a.length - 1; i++){
int min = i;
int minVal = a[i];
for (int j = i + 1; j < a.length ; j++) {
if(a[j] < minVal){
min = j;
minVal = a[j];
}
}
if(min != i){
a[min] = a[i];
a[i] = minVal;
}
}
}
3.插入排序
public static void inserSort(int[] nums){
if(nums == null || nums.length < 2){
return;
}
for (int i = 1; i < nums.length; i++){
int num = nums[i];
int j = i - 1;
while (j >= 0 && num < nums[j]) {
nums[j+1] = nums[j];
j--;
}
nums[j + 1] = num;
}
}
public static void main(String[] args) {
int a[] = { 6, 5, 3, 1, 8, 7, 2, 4 };
int n =a.length;
inserSort(a);
System.out.println("鸡尾酒排序结果:");
for (int i = 0; i < n; i++)
{
System.out.println("i=" + a[i]);
}
}
4.希尔排序
/**
* 全部元素分为几个区域来提升插入排序的性能。
* 这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,
* 算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)
* 分类 -------------- 内部比较排序
* 数据结构 ---------- 数组
* 最差时间复杂度 ---- 根据步长序列的不同而不同。已知最好的为O(n(logn)^2)
* 最优时间复杂度 ---- O(n)
* 平均时间复杂度 ---- 根据步长序列的不同而不同。
* 所需辅助空间 ------ O(1)
* 稳定性 ------------ 不稳定
*
* @param a
* @param n
*/
static void shellSort(int a[], int n) {
int h = 0;
// 生成初始增量
while (h <= n / 3)
{
h = 3 * h + 1;
}
while (h >= 1) {
for (int i = h; i < n; i++) {
int j = i - h;
int get = a[i];
while (j >= 0 && a[j] > get) {
a[j + h] = a[j];
j = j - h;
}
a[j + h] = get;
}
h = (h - 1) / 3; // 递减增量
}
}
5. 归并排序
/**
* @description 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
* 设定两个指针,最初位置分别为两个已经排序序列的起始位置
* 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
* 重复步骤3直到某一指针到达序列尾
* 将另一序列剩下的所有元素直接复制到合并序列尾
* @date 2018/7/12
*/
public class MergeSort {
// 分类 -------------- 内部比较排序
// 数据结构 ---------- 数组
// 最差时间复杂度 ---- O(nlogn)
// 最优时间复杂度 ---- O(nlogn)
// 平均时间复杂度 ---- O(nlogn)
// 所需辅助空间 ------ O(n)
// 稳定性 ------------ 稳定
// 合并两个已排好序的数组A[left...mid]和A[mid+1...right]
public static void merge(int num[], int left, int mid, int right) {
int len = right - left + 1;
int[] tempArray = new int[len]; // 辅助空间O(n)
int index = 0;
int i = left; // 前一数组的起始元素
int j = mid + 1; // 后一数组的起始元素
while (i <= mid && j <= right) {
tempArray[index++] = num[i] <= num[j] ? num[i++] : num[j++]; // 带等号保证归并排序的稳定性
}
while (i <= mid) {
tempArray[index++] = num[i++];
}
while (j <= right) {
tempArray[index++] = num[j++];
}
for (int k = 0; k < len; k++) {
num[left++] = tempArray[k];
}
}
/**
* 递归实现的归并排序(自顶向下)
*/
public static void mergeSortRecursion(int num[], int left, int right) {
// 当待排序的序列长度为1时,递归开始回溯,进行merge操作
if (left == right) {
return;
}
int mid = (left + right) / 2;
mergeSortRecursion(num, left, mid);
mergeSortRecursion(num, mid + 1, right);
merge(num, left, mid, right);
}
/**
* 非递归(迭代)实现的归并排序(自底向上)
*/
public static void mergeSortIteration(int num[], int len) {
// 子数组索引,前一个为num[left...mid],后一个子数组为num[mid+1...right]
int left, mid, right;
// 子数组的大小i初始为1,每轮翻倍
for (int i = 1; i < len; i *= 2) {
left = 0;
// 后一个子数组存在(需要归并)
while (left + i < len) {
mid = left + i - 1;
// 后一个子数组大小可能不够
right = mid + i < len ? mid + i : len - 1;
merge(num, left, mid, right);
// 前一个子数组索引向后移动
left = right + 1;
}
}
}
public static void main(String[] args) {
int nums[] = {6, 5, 3, 1, 8, 7, 2, 4}; // 从小到大归并排序
int nums2[] = {6, 5, 3, 1, 8, 7, 2, 4};
int n1 = nums.length;
int n2 = nums2.length;
mergeSortRecursion(nums, 0, n1 - 1); // 递归实现
mergeSortIteration(nums2, n2); // 非递归实现
System.out.println("递归实现的归并排序结果:");
for (int i = 0; i < n1; i++) {
System.out.println(nums[i]);
}
System.out.println();
System.out.println("非递归实现的归并排序结果:");
for (int i = 0; i < n2; i++) {
System.out.println(nums2[i]);
}
}
}