您的位置:首页 > 编程语言 > Java开发

算法学习笔记——排序问题

2016-11-14 16:28 246 查看
学习笔记,仅做记录,如有错漏,望指出,谢谢。

1.简单选择排序(选择类排序)

使用方法:蛮力法

平均时间复杂度为:O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),稳定(排序算法稳定性详见百度百科)

空间复杂度为O(1)

∑i=0n−2∑j=i+1n−1=∑i=0n−2(n−i−1)=n(n−1)2=O(n2)

package com.viper.sort;

public class SelectSort {

public static void sort(int array[]) {
for (int i = 0; i < array.length; i++) {
int index = i;
for (int j = i + 1; j < array.length; j++) {
// 查找无序区最小的记录
if (array[j] < array[index])
index = j;
}
if (index != i) {
// 将无序区最小的记录添加到有序区末尾
int temp = array[i];
array[i] = array[index];
array[index] = temp;
}
}
}
}


2.冒泡排序(交换类排序)

使用方法:蛮力法

平均时间复杂度为:O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),空间复杂度为O(1),稳定

首先将元素分为有序区和无序区,初始时,有序区为零。遍历比较无序区中的相邻元素,将较大元素后移,并记录每次最后发生交换的位置,以确定有序区和无序区。重复遍历比较无序区中相邻元素直至无序区为零。

package com.viper.sort;

public class BubbleSort {

public static void sort(int[] array) {
int bound, exchange = array.length - 1;
while (exchange != 0) {
bound = exchange;
exchange = 0;//重置为零,若未交换则排序完毕
for (int i = 0; i < bound; i++) {
if (array[i] > array[i + 1]) {
int temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
exchange = i;//记录每次交换的位置
}
}
}
}
}


3.快速排序(交换类排序)

使用方法:分治法

平均时间复杂度为O(nlog2n)最坏时间复杂度为O(n2),最好时间复杂度为O(nlog2n),空间复杂度为O(nlog2n),不稳定

对待排序元素进行扫描,确定中间的轴值,以轴值为划分,一侧元素均小于轴值,一侧元素均大于轴值。对以轴值划分的区域递归排序。

package com.viper.sort;

public class QuickSort {

public static void sort(int[] array) {
quickSort(array, 0, array.length - 1);
}

/**
* 快速排序
*/
private static void quickSort(int[] array, int first, int end) {
int pivot;
if (first < end) {
pivot = partition(array, first, end);
quickSort(array, first, pivot - 1);
quickSort(array, pivot + 1, end);
}
}

/**
* 扫描并划分待排序元素,返回轴值
*/
private static int partition(int array[], int first, int end) {
int i = first, j = end;
while (i < j) {// i==j停止,确定轴值
while (i < j && array[i] <= array[j]) {
j--;
}
if (i < j) {
swap(array[i], array[j]);
i++;
}
while (i < j && array[i] <= array[j]) {
i++;
}
if (i < j) {
swap(array[i], array[j]);
j--;
}
}
return i;
}

private static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
}


5.归并排序

使用方法:分治法

时间复杂度为O(nlog2n)(执行一次合并算法的时间复杂度为O(n)),空间复杂度为O(n),稳定

对待排序序列进行划分,直至序列有序(即序列长度为1),对有序子序列进行合并,直至排序完成

package com.viper.sort;

public class MergeSort {

public static void sort(int[] array) {
mergeSort(array, 0, array.length - 1);
}

private static void mergeSort(int[] array, int start, int end) {
if (start == end) {
return;
} else {
int mid = (start + end) / 2;
//递归划分
mergeSort(array, start, mid);
mergeSort(array, mid + 1, end);
//合并子序列
merge(array, start, mid, end);
}
}

private static void merge(int[] array, int start, int mid, int end) {
int[] tempArr = new int[array.length];
int i = start, j = mid + 1, k = start;
while (i < mid && j < end) {
if (array[i] <= array[j]) {
tempArr[k++] = array[i++];
} else {
tempArr[k++] = array[j++];
}
}
//将未处理完的序列依次放入结果中
while (i <= mid) {
tempArr[k++] = array[i++];
}
while (j <= end) {
tempArr[k++] = array[j++];
}
//将已排序序列复制回原序列
while(start <= k) {
array[k] = tempArr[k--];
}
}
}


4.直接插入排序(插入类排序)

使用方法:减治法

平均时间复杂度为O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),空间复杂度为O(1),稳定

将待排序序列划分为有序区和无序区,初始有序区元素个数为零,取无序区第一个元素,与有序区元素逐个毕竟,插入到合适位置,直至无序区元素个数为零

package com.viper.sort;

public class InsertSort {
public static void sort(int[] array) {
for (int i = 1; i < array.length; i++) {
int j, temp = array[i];
for (j = i - 1; j > 0 && temp < array[j]; j--) {
array[j + 1] = array[j];
}
array[j + 1] = temp;
}
}
}


6.堆排序(选择类排序)

使用方法:减治法

堆(heap)是具有下列性质的完全二叉树:每个结点的值都小于(大于)或等于其左右孩子结点的值

时间复杂度为O(nlog2n),空间复杂度为O(1),不稳定

package com.viper.sort;

public class HeapSort {

public static void sort(int[] array) {
int i, temp;
for (i = array.length - 1; i >= 0; i--) {
siftHeap(array, i, array.length);// 初始建堆,从最后一个分支开始
}

for (i = 1; i < array.length; i++) {
temp = array[0];
array[0] = array[array.length - i];
array[array.length - i] = temp;
siftHeap(array, 0, array.length - i);//调整当前根结点
}
}

/**
* 筛选法调整堆
*/
private static void siftHeap(int[] array, int k, int n) {
int i = k, j = 2 * i + 1, temp;// i根结点,j指向左孩子
while (j < n) {// 判断是否为叶子结点
if (j < n - 1 && array[j] < array[j + 1]) {
j++;
}
if (array[i] > array[j]) {// 根结点值较大
break;
} else {// 交换根结点与较大孩子结点
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}


7.希尔排序(插入类排序)

平均时间复杂度为O(nlog2n),最坏时间复杂度为O(nlog2n),空间复杂度为O(1),希尔排序不稳定

package com.viper.sort;

public class ShellSort {

public static void sort(int[] array) {
for (int step = 5;step > 0; step--) {//此处step默认为5
for (int i = 0; i < step; i++) {// 每一组
for (int j = i + step; j < array.length; j += step) {// 插入排序
int k, temp = array[j];
for (k = j - step; k >= 0 && temp < array[k]; k -= step) {
array[k + step] = array[k];
}
array[j + step] = temp;
}
}
}
}
}


8.基数排序

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 Java