排序稳定性的含义:
如果排序算法能够保留数组中重复元素的的相对位置则可以被称为是稳定的,比如我们要根据两个键对数据进行排序,按照第一个主要键排好序之后,再对第二个键排序,这个时候排序算法的稳定性就非常重要
常见的稳定的排序有冒泡排序 插入排序 归并排序
不稳定的排序有选择排序 希尔排序 快速排序 三向快速排序 和堆排序
冒泡排序
冒泡排序每次都是比较相邻的两个元素,若这两个相邻的元素相等则不会交换位置,所以冒泡跑排序是稳定的,内层循环结束就把最大的元素放到后面了,外层循环i控制每次冒泡都是从第一个元素开始,里层循环结束的条件是a.length-i,因为走了i+1趟之后后面i+1和元素就有序了,所以不用再对后面的元素比较,减少了比较次数
public class Bubble {
public static void bubble(int a[]){
for(int i=0;i<a.length;i++){
for(int j=1;j<a.length-i;j++){
if(a[j]<a[j-1]){
int temp=a[j-1];
a[j-1]=a[j];
a[j]=temp;
}
}
}
}
测试用例:3241
打印每趟之后的结果,发现后面一趟是重复的,所以继续优化,减少趟数
public class Bubble2 {
public static void bubble(int a[]){
for(int i=0;i<a.length;i++){
boolean sorted=true;
for(int j=1;j<a.length-i;j++){
if(a[j]<a[j-1]){
int temp=a[j-1];
a[j-1]=a[j];
a[j]=temp;
sorted=false;
}
}
if(sorted){
break;
}
Bubble.printarray(a);
System.out.println();
}
}
插入排序
选择排序
选择排序就是首先选择数组中最小的元素和第一个元素交换,再次从剩下的元素中找到最小的元素和第二个元素交换,选择排序不会维持相等元素的相对位置,比如数组是 3, 4, 3,1,,第一趟3和1交换,则破坏了原来3和3的顺序所以是不稳定的
public static void selection(int[] a) {
for (int i = 0; i < a.length; i++) {
int min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
}
}
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
插入排序
假设前n-1个元素已经有序了,然后找到n这个元素的正确位置进行插入,当第n个元素比n-1是元素小,说明需要把第n个元素往前插,那么从当前位置开始往前遍历,找打n元素的位置,并把和她比较过仍然比她大的元素向后移动,为她腾出位置,一直到一个比她小的元素,结束,把这个元素放在这。是一种稳定的插入排序算法,对于已经有序的序列性能较好。
public static void insertSort(int arr[]){
int j=0;
for(int i=1;i<arr.length;i++){
if(arr[i]<arr[i-1]){
int num=arr[i];
for(j=i-1;j>=0 && arr[j]>num;j--){
arr[j+1]=arr[j];
}
arr[j+1]=num;
}
}
}
快速排序算法
一般选取第一个元素为基准值
从后往前,找比基准值小的数,交换到前面
从前往后找比基准值大的数,交换到后面,一直到start指针与end指针重合,一趟快速排序的过程完成,这个时候start所在的位置就是基准值的正确位置,返回这个值
然后根据这个位置,把原数组分成两部分,继续递归上述过程,知道每部分的只有一个数
public class QuickSort {
public static void quickSort(int arr[]){
qsort(arr,0,arr.length-1);
}
private static void qsort(int[] arr, int start, int end) {
if(start<end){
int temp=partition(arr,start,end);//返回的是基准的正确位置
qsort(arr, start, temp-1);//以基准分成左右两个部分
qsort(arr, temp+1, end);
}
}
private static int partition(int[] arr, int start, int end) {
int temp=arr[start];//把基准值存起来
while(start<end){//以一个基准的一趟快速排序,这个循环结束,基准元素到了自己正确的位置
while(start<end && arr[end]>=temp){
end--;//从后往前找比基准小的位置
}
arr[start]=arr[end];//这时候的end所在的元素就是比基准小,交换到左边
while(start<end && arr[start]<=temp){
start++;//从前往后找比基准大的元素
}
arr[end]=arr[start];//找到以后交换到右边,继续找
}
arr[start]=temp;
return start;
}
public static void main(String[] args) {
int arr[]={5,8,2,9,4,7,3,1,6};
quickSort(arr);
for (int i : arr) {
System.out.println(i);
}
}
}