常用的排序算法有:冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序。
public class Sort {
/**
* 冒泡排序(由小到大排序)
* 思路:对于给定的n个记录,从最后一个记录开始依次对相邻的两个记录进行比较,当后面的记录小于前面的记录时,交换位置,
* 进行一轮比较和换位后,n个记录中的最小记录位于第1位;然后对后n-1个记录进行第二轮比较;重复该过程直到进行比较的记录只剩下一个为止。
*/
public void bubbleSort(int [] array){
for(int i=0;i<array.length-1;i++){
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;
}
}
}
}
/**
* 选择排序(由小到大排序)
* 思路:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置交换;
* 接着对不包括第一个记录的其他记录进行第二轮比较,得到最小记录并与第二个记录进行位置交换;
* 重复该过程,直到进行比较的记录只有一个时为止。
*/
public void selectSort(int [] array){
for(int i=0;i<array.length-1;i++){
int min=array[i];
int flag=i;
for(int j=i+1;j<array.length;j++){
if(min>array[j]){
min=array[j];
flag=j;
}
}
if(flag!=i){
array[flag]=array[i];
array[i]=min;
}
}
}
/**
* 插入排序(由小到大排序)
* 思路:对于给定的一组记录,初始时假设第一个记录自成一个有序序列,其余记录为无序序列;
* 接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插入到有序序列中为止。
*/
public 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;
while(j>=1 && array[j-1]>temp){
array[j]=array[j-1];
j--;
}
array[j]=temp;
}
}
}
/**
* 希尔排序(由小到大排序)
* 思路:先将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对各个子序列分别进行直接插入排序,
* 待整个待排序序列“基本有序后”,最后再对所有元素进行一次直接插入排序。
* 希尔排序具体步骤:
* 1.选择一个步长序列t1,t2,...,tk,满足ti>tj (i<j),且tk=1
* 2.按步长序列个数k,对待排序序列进行k趟排序
* 3.每趟排序,根据对应的步长ti,将待排序列分割成ti个子序列,分别对各个子序列进行直接插入排序。
*/
public void shellSort(int [] array){
int len=array.length;
for(int h=len/2;h>0;h=h/2){//h表示步长
for(int i=h;i<len;i++){
int temp=array[i];
int j=i;
while(j>=h && array[j-h]>temp){
array[j]=array[j-h];
j-=h;
}
array[j]=temp;
}
}
}
/**
* 堆排序(由小到达排序)
* 思路:对于给定的n个记录,初始时把这些记录看作一棵顺序存储的二叉树,然后将其调整为一个大顶堆,
* 然后将堆的最后一个元素与堆顶元素(即二叉树的根节点)进行交换后,堆的最后一个元素即为最大记录;
* 接着将前n-1个元素(即不包括最大记录)重新调整为一个大顶堆,再将堆顶元素与当前堆的最后一个元素进行交换后得到次最大记录;
* 重复该过程直到调整的堆中只剩一个元素时为止,该元素即为最小记录,此时得到一个有序序列。
* 简化思路:1.建立大顶推2.交换第一个元素和最后一个元素的值3.重复以上步骤,不过每次参与建堆的元素个数比上一次减一
*/
public void heapSort(int [] array){
int len=array.length;
for(int i=len/2;i>=0;i--){//从下往上,从右往左建立初始大顶堆
heapAdjust(array,i,len-1);
}
//
for(int i=len-1;i>=0;i--){
int temp=array[0];
array[0]=array[i];
array[i]=temp;
heapAdjust(array,0,i-1);
}
}
public void heapAdjust(int [] array,int parent,int len){
int temp=array[parent];
for(int i=2*parent+1;i<=len;i*=2+1){
if(i+1<=len && array[i+1]>array[i]){
i++;
}
if(array[i]<=temp){
break;
}
array[parent]=array[i];
array[i]=temp;
parent=i;
}
}
/**
* 归并排序(由小到大排序)
* 思路:对于给定的n个记录,首先将每两个相邻的长度为1的子序列进行归并,得到n/2(向上取整)个长度为2或1的有序子序列,
* 再将其两两归并,反复执行此过程,直到得到一个有序序列。
* 归并排序的关键两步:1.划分半子表;2.合并半子表
*/
public void mergeSort(int [] list){
for(int gap=1;gap<list.length;gap*=2){
mergeSort1(list,gap);
}
}
public void mergeSort1(int [] list,int gap){
int i;
for(i=0;i+2*gap-1<list.length;i+=2*gap){
merge(list,i,i+gap,i+2*gap-1);
}
if(i+gap<list.length){
merge(list,i,i+gap,list.length-1);
}
}
public void merge(int [] list,int low,int mid,int high){
if(low>=mid || mid>high) return ;
int i=low,j=mid,n=0;
int [] temp=new int[high-low+1];
while(i<mid && j<=high){
if(list[i]<=list[j]){
temp[n++]=list[i++];
}else{
temp[n++]=list[j++];
}
}
while(i<mid) temp[n++]=list[i++];
while(j<=high) temp[n++]=list[j++];
//
for(int k=0;k<high-low+1;k++){
list[low+k]=temp[k];
}
}
/**
* 快速排序(由小到大排序)
* 思路:对于给定的n个记录,通过一趟排序后,将原序列分为两部分,其中前一部分的所有记录均比后一部分的所有记录小,
* 然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中所有记录均有序为止。
* 算法具体步骤:
* 1.分解:将输入的序列array[m...n]划分成两个非空子序列array[m...k]和array[k+1...n],
* 使array[m...k]中任一元素的值不大于array[k+1...n]中的任一元素的值;
* 2.递归求解:通过递归调用快速排序算法分别对array[m...k]和array[k+1...n]进行排序
* 3.合并:由于对分解出的两个子序列的排序是就地进行的,所以在array[m...k]和array[k+1...n]都排好后不需要执行任何计算array[m...n]就已经排好序。
*/
public void quickSort(int [] array){
quickSort1(array,0,array.length-1);
}
public void quickSort1(int [] array,int start,int end){
if(start>=end){
return ;
}
int pivot=partition(array,start,end);
quickSort1(array,start,pivot-1);
quickSort1(array,pivot+1,end);
}
public int partition(int [] array,int low,int high){
int temp=array[low];
int left=low,right=high;
while(left<right){
while(right>left && array[right]>=temp){
right--;
}
if(right>left){
array[left]=array[right];
}
while(left<right && array[left]<=temp){
left++;
}
if(left<right){
array[right]=array[left];
}
}
array[left]=temp;
return left;
}
public static void main(String [] args){
Sort s=new Sort();
int [] a={5,2,3,7,8,1,4};
s.quickSort(a);
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}
本博客的内容来自《Java程序员面试笔试宝典》
关于各种排序算法的性能可以参看此博客:各种排序算法的稳定性和时间复杂度小结