近日复习内部排序,仔细体会了严蔚敏老师的数据结构,深受启发,总结如下:
1 绪论
排序有两大操作组成,一是比较关键字大小,这个不可避免,二是将记录从一个位置移动到另一个位置,这可通过存储方式来尽力避免。
总的来说排序分为以下几种:内部排序和外部排序,而内部排序分为插入排序,
2 插入排序
2.1 简单插入排序,
public static void insertSort(int[] array){
int tmp;
int j;
for(int i=1;i<array.length;i++){
tmp = array[i];
if(tmp<array[i-1]){
for(j=i;j>0 && tmp<array[j-1];j--){
array[j]=array[j-1];
}
array[j]=tmp;
}
}
}
后来发现代码可以进一步优化,少比较一次
public static void insertSort(int[] array){
int tmp;
int j;
for(int i=1;i<array.length;i++){
tmp = array[i];
for(j=i;j>0 && tmp<array[j-1];j--){
array[j]=array[j-1];
}
array[j]=tmp;
}
}
简单插入pai x算法复杂度为O(n^2)
2.2 希尔排序
希尔排序也是缩小增量排序,主要灵感来自于以下两点:
1. 简单插入排序在n很小时,效率比较高 2. 简单插入排序在序列为基本有序的情况下,效率较高
综合以上两点,希尔排序循环次数,即多一层循环,将复杂的大任务,分解成效率较高的多个小任务。希尔排序的最大优点在于,数值的移动并不是一次一个单位,可以“跳跃式”移动。
public static void shellSort(int[] array){
int[] dks = {5,3,1};
for(int dk:dks){
shellInsert(array,dk);
}
}
public static void shellInsert(int[] array,int dk){
/*
* 对每一次进行增量为dk的简单插入排序
* */
int tmp,j;
for(int i=dk;i<array.length;i++){
tmp = array[i];
for(j=i;j>(dk-1)&&array[j-dk]>tmp;j-=dk){
array[j]=array[j-dk];
}
//System.out.println(j);
array[j]=tmp;
}
}
希尔排序的复杂度比较难以计算,需要注意的是,增量的设置中应该使序列中没有除去1以外的公因式,且最后一个增量必须为1.
3. 交换排序
3.1 冒泡排序
冒泡排序的复杂度比较简单,为O(n^2)
public static void bubbleSort(int[] array){
int min;
for(int i=0;i<array.length;i++){
for(int j=array.length-1;j>i;j--){
if(array[j-1]>array[j]){
min = array[j];
array[j]= array[j-1];
array[j-1] = min;
}
else{
min = array[j];
}
}
}
}
3.2 快速排序
public static void QSort(int[] array,int low,int high){
int pos;
if(low<high){
pos = quickSort(array,low,high);
QSort(array,low,pos-1);
QSort(array,pos+1,high);
}
}
//quick sort
public static int quickSort(int[] array,int low,int high){
//int low = 0;
//int high = array.length-1;
int tmp = array[low];
while(low<high){
while(low<high && array[high]>=tmp){
high--;
}
array[low]=array[high];
while(low<high && array[low]<=tmp){
low++;
}
array[high]=array[low];
}
array[low]=tmp;
return low;
}