目录
1、冒泡排序
比较相邻的元素。如果第一个比第二个大,就交换它们两个;
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
针对所有的元素重复以上的步骤,除了最后一个;
重复步骤1~3,直到排序完成。
public void bubbleSort(int[] A){
for(int i=0;i<A.length-1;i++){
for(int j=0;j<A.length-i-1;j++){
if(A[j]>A[j+1]){
int temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
}
时间复杂度O(),空间复杂度O(1)。
2、选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
以此类推,直到所有元素均排序完毕。
public static void selectionSort(int[] a) {
int n = a.length;
for (int i = 0; i < n; i++) {
int k = i;
// 找出最小值的下标
for (int j = i + 1; j < n; j++) {
if (a[j] < a[k]) {
k = j;
}
}
// 将最小值放到未排序记录的第一个位置
if (k > i) {
int tmp = a[i];
a[i] = a[k];
a[k] = tmp;
}
}
}
时间复杂度O(),空间复杂度O(1)。
3、插入排序
从第一个元素开始,该元素可以认为已经被排序;
取出下一个元素,在已经排序的元素序列中从后向前扫描;
如果该元素(已排序)大于新元素,将该元素移到下一位置;
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
将新元素插入到该位置后;
重复步骤2~5。
public static void insertSort(int[] A){
for(int i=1;i<A.length;i++){
int temp = A[i];
for(int j=i-1;j>=0;j--){
if(A[j]>temp){
A[j+1] = A[j];
A[j] = temp;
}else{
A[j+1] = temp;
break;
}
}
}
}
时间复杂度O(),空间复杂度O(1)。
4、希尔排序
希尔排序的原理:
根据需求,如果你想要结果从小到大排列,它会首先将数组进行分组
然后将较小值移到前面,较大值移到后面,最后将整个数组进行插入排序
这样比起一开始就用插入排序减少了数据交换和移动的次数,可以说希尔排序是加强版的插入排序
public static void shellSort(int[] a){
for(int increment=a.length/2;increment>0;increment/=2){
for(int i=increment;i<a.length;i++){
int temp = a[i];
for(int j=i;j>=increment;j=j-increment){
if(a[j-increment]>temp){
a[j]=a[j-increment];
}else{
break;
}
}
a[j]=temp;
}
}
}
最坏时间复杂度O(),最好时间复杂度O(n),空间复杂度O(1)
5、归并排序
把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序;
将两个排序好的子序列合并成一个最终的排序序列
public static int[] sort(int[] nums, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
// 左边
sort(nums, low, mid);
// 右边
sort(nums, mid + 1, high);
// 左右归并
merge(nums, low, mid, high);
}
return nums;
}
public static void merge(int[] nums, int low, int mid, int high) {
int[] temp = new int[high - low + 1];
int i = low;// 左指针
int j = mid + 1;// 右指针
int k = 0;
// 把较小的数先移到新数组中
while (i <= mid && j <= high) {
if (nums[i] < nums[j]) {
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
}
}
// 把左边剩余的数移入数组
while (i <= mid) {
temp[k++] = nums[i++];
}
// 把右边边剩余的数移入数组
while (j <= high) {
temp[k++] = nums[j++];
}
// 把新数组中的数覆盖nums数组
for (int k2 = 0; k2 < temp.length; k2++) {
nums[k2 + low] = temp[k2];
}
}
时间复杂度O(nlogn),空间复杂度O(n)。
6、快速排序
从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
public static void quickSort(int[] numbers,int low,int high)
{
if(low < high)
{
int middle = getMiddle(numbers,low,high); //将numbers数组进行一分为二
quickSort(numbers, low, middle-1); //对低字段表进行递归排序
quickSort(numbers, middle+1, high); //对高字段表进行递归排序
}
}
public static int getMiddle(int[] numbers, int low,int high)
{
int temp = numbers[low]; //数组的第一个作为中轴
while(low < high)
{
//下面这个判断是>=,如果没有=,会导致死循环,比如[5,1,1,2,0,0]这个用例
while(low < high && numbers[high] >= temp)
{
high--;
}
numbers[low] = numbers[high];//比中轴小的记录移到低端
while(low < high && numbers[low] <= temp)
{
low++;
}
numbers[high] = numbers[low] ; //比中轴大的记录移到高端
}
numbers[low] = temp ; //中轴记录到尾
return low ; // 返回中轴的位置
}
时间复杂度O(nlogn),空间复杂度O(logn)~O(n)。
7、堆排序
将数组构建成一个最大堆(也就是根节点最大);
取出根节点(交换堆顶和最后一个元素);
将剩下的数组元素在建成一个最大二叉堆,返回第2步,直到所有元素都被取光
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args){
int[] nums = {49,38,65,97,76,13,27,49,78,34,12,64};
//循环构建最大堆
for(int i=0;i<nums.length-1;i++){
buildMaxHeap(nums,nums.length-1-i);
//交换堆顶和最后一个元素(当前最大的值放到数组末尾)
swap(nums,0,nums.length-1-i);
System.out.println(Arrays.toString(nums));
}
}
public static void buildMaxHeap(int[] array,int lastIndex){
/*
二叉树规律:(根节点为节点 0 )
节点 i 的左子节点为节点 2*i+1,右子节点为节点2*i+2
*/
//从lastIndex处的节点(最后一个节点)的父节点开始
for(int i=(lastIndex-1)/2;i>=0;i--){
//k为当前正在被判断的节点
int k = i;
//节点 k 拥有子节点
if(2*k+1<=lastIndex){
//biggerIndex记录子节点中较大的一个
int biggerIndex = 2*k+1;
//如果存在右子节点,并且右子节点的值大于左子节点,更新biggerIndex
if(biggerIndex+1<=lastIndex&&array[biggerIndex+1]>array[biggerIndex]){
biggerIndex++;
}
//如果节点 k 的值小于它较大子节点的值,则交换
if(array[k]<array[biggerIndex]){
swap(array,k,biggerIndex);
}
}
}
}
public static void swap(int[] array,int i,int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
时间复杂度O(nlogn),空间复杂度O(1)