前言
练练手,也方便以后查看。希尔排序和基数排序,还不会。。。占个位,学会了再来补充。
这里列出的排序算法共六种:
1. 冒泡排序,
2. 快速排序,
3. 插入排序,
4. 选择排序
5. 归并排序,
6. 堆排序。
其中稳定的排序只有冒泡排序、归并排序、插入排序。
选择排序是不稳定的,原因如下:
序列5 8 5 2 9,第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
排序的稳定性:
排序算法的稳定性是指在待排序的序列中,存在多个相同的元素,若经过排序后这些元素的相对词序保持不变,即Xm=Xn,排序前m在n前,排序后m依然在n前,则称此时的排序算法是稳定的。
优化版冒泡排序
思想:
内循环就是冒泡,即通过相邻比较,每轮循环确定一个最小值。
外循环用来确定循环多少轮。
最后加上flag,进行优化(如果内循环中的if没成立,说明已排好序)
public static void bubbleSort(int[] array){
boolean flag = true;
for(int i=0;i<array.length-1 && flag;i++){
flag = false;
for(int j=array.length-1;j>i;j--){
if(array[j]<array[j-1]){
int temp = array[j];
array[j] = array[j-1];
array[j-1] = temp;
flag = true;
}
}
}
}
快排
思想:
一个core方法,选择第一个数为基值,然后将数据与基值比较分成两部分,小于基值的在左,大于基值的在右,最后空位存放基值。
然后对分好的两部分递归处理,直至递归处理的数据只有一个。
public static void quickSort(int[] array,int low,int high){
if(low<high){
int middle = core(array,low,high);
quickSort(array,low,middle-1);
quickSort(array,middle+1,high);
}
}
private static int core(int[] array,int low,int high){
int provit = array[low];
while(low<high){
while(low<high && array[high]>=provit)
high--;
array[low] = array[high];
while(low<high && array[low]<=provit)
low++;
array[high] = array[low];
}
array[low] = provit;
return low;
}
插入排序
思想:
将数据分成两部分,一部分是未排序的,一部分是已排序的,不断的将未排序的元素插入到已排序的区域中。
public static void insertSort(int[] array){
for(int i=1;i<array.length;i++){//未排区域的每个数都要进行排序
if(array[i]<array[i-1]){//判断当前元素是否需要排序
int temp = array[i];
int j=i-1;
for(;j>=0;j--){//移动已排好区域的元素
if(temp<array[j])
array[j+1] = array[j];
else//这步不能少
break;
}
array[j+1] = temp;//把待排元素插入到空出来的那个位置
}
}
}
选择排序
思想:
类似冒泡。
在内循环中,只需找到最小值的下标,最后才交换。每轮循环找到一个最小的值。
外循环则确定有多少个数要排序。
public static void selectSort(int[] array){
for(int i=0;i<array.length-1;i++){
int min = i;
for(int j=array.length-1;j>i;j--){
if(array[j]<array[min])
min = j;
}
if(min!=i){
int temp = array[min];
array[min] = array[i];
array[i] = temp;
}
}
}
归并排序
思想:
递归。将数据分成两部分,再将每部分分成两部分,直至不能再分。拆到最后,再合并。一直往上层返回,然后继续合并。
public static void mergeSort(int[] array,int low,int high,int[] temp){
if(low<high){
int middle = low + (high-low)/2;
mergeSort(array,low,middle,temp);//对两部分递归处理
mergeSort(array,middle+1,high,temp);//对两部分递归处理
merge(array,low,high,middle,temp);//合并
}
}
//用于合并的方法
private static void merge(int[] array,int low,int high,int middle,int[] temp){
int m = low;
int n = middle+1;
int j = middle;
int k = high;
int i =0;
while(m<=j && n<=k){//等号不能少
if(array[m]<array[n]){
temp[i++] = array[m++];
}else{
temp[i++] = array[n++];
}
}
while(m<=j)
temp[i++] = array[m++];
while(n<=k)
temp[i++] = array[n++];
for(int ii=0;ii<i;ii++){
array[low+ii] = temp[ii];
}
}
堆排序
思想:
先通过heapAdjust方法来初始化一个大顶堆。然后循环将第一个元素即最大的元素放到最后面然后再调整堆。
public static void heapSort(int[] array){
//从叶子节点开始,对每个非叶子节点进行堆调整
for(int i=(array.length-1)/2;i>=0;i--){
heapAdjust(array,i,array.length);
}
//开始堆排序
for(int i=array.length-1;i>=0;i--){
int temp = array[0];
array[0] = array[i];
array[i] = temp;
heapAdjust(array,0,i);//i在这里表示有效长度哦
}
}
//调整堆,大顶堆
//length表示数组有效长度(从0开始)
private static void heapAdjust(int[] array,int s,int length){
int temp = array[s];
for(int i=2*s;i<length;i=2*i){
if(i+1<length && array[i]<array[i+1])
i++;
if(temp>=array[i])
break;
array[s] = array[i];
s = i;
}
array[s] = temp;
}