排序:冒泡排序、简单排序、直接插入排序、希尔排序、堆排序、归并排序、快速排序。
排序算法对比
排序算法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n2) | O(n) | O(n2) | O(1) | 稳定 |
简单排序 | O(n2) | O(n2) | O(n2) | O(1) | 稳定 |
直接插入排序 | O(n2) | O(n) | O(n2) | O(1) | 稳定 |
希尔排序 | O(nlogn)~O(n2) | O(n1.3) | O(n2) | O(1) | 不稳定 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | O(n2) | O(logn)~O(n) | 不稳定 |
冒泡排序:双层循环,外层从后往前,比值后将小的数放到前面。
/**
* 冒泡排序
*/
public void BubbleSort(int a[]){
for (int i = a.length-1; i > 0; i--)
{
boolean isOrdered = true;//是否已经有序
for (int j = 0; j < i; j++)
{
if(a[i]<a[j]){
Swap(a,i,j);
isOrdered = false;//有交换,还不是有序
}
}
}
}
简单排序:两层循环,记第一位为最小值,第二层与最小值比较,比最小值小则更新最小值的位置,直到里层循环结束,交换位置。
/**
* 选择排序
* @param array
*/
public void SelectSort(int array[]){
int min = 0;
for(int i = 0;i<array.length;i++){
min = i;
for(int j = i+1;j<array.length;j++){
if(array[min]>array[j]){
min = j;
}
}
if(min!=i){
Swap(array, i, min);
}
}
}
直接插入排序:将一个数插入到已排好序的有序数列中,得到一个新数列增量加一。两层循环,外层从第二个数开始,将外层的数插入到里层的合适位置,循环加一。比较将比a[i]的值存在temp里,在i前面比temp大的数依次往后放一位知道遇到比temp小的,交换位置。
/**
* 插入排序
* @param array
*/
void insertSort(int[]a){
for(int i=1;i<a.length;i++){
int tmp = a[i];
int p = i;
for(int j = i-1;j>=0;j--){
if(tmp<a[j]){
a[j+1] = a[j];
p--;
}
}
a[p] = tmp;
}
}
希尔排序:按相距某个增量的将数分堆,堆内通过直接插入排序。
/**
* 希尔排序
* @param array
*/
public void ShellSort(int array[]){
int group = array.length;
do{
group = group/3;
for(int i = group;i<array.length;i++){
for(int j = i-group; j>=0; j-=group){
if(array[j]>array[j+group]){
Swap(array, j, j+group);
}
}
Print(array);
}
System.out.println(group);
}
while(group>1);
}
堆排序:将数组调整为大顶堆,把顶和尾互换,调整数组长度减一。调整大顶堆,将该数与其两个子节点比较,先比较两个子节点,将大的数与i比较大小。其子节点分别为2*i和2*i+1。
/**
* 堆排序
* @param array
*/
public void HeapSort(int array[]){
for(int i = array.length/2;i>0;i--){
HeapAdjust(array,i,array.length);//构建大顶堆
}
Print(array);
for(int i = array.length;i>1;i--){
Swap(array, 0, i-1);
HeapAdjust(array,1,i-1);
}
}
public void HeapAdjust(int array[],int i,int len){
int temp = array[i-1];
for(int j = i*2; j<=len; j*=2){
if(j<len && array[j-1]<array[j]){
++j;
}
if(temp>=array[j-1])
break;
array[i-1] = array[j-1];
i = j;
}
array[i-1] = temp;
}
归并排序:将数分为n个子序列,两两归并直到结束。
/**
* 递归的归并排序
*/
public void MergeSort(int array[]){
MSort(array,0,array.length-1);
}
public void MSort(int array[],int left,int right){
if(left>=right)
return;
int center = (left+right)/2;
MSort(array, left, center);
MSort(array, center+1, right);
Merge(array, left, center, right);
}
public void Merge(int array[],int i,int center,int n){
int k,j;
// 临时数组
int[] tmpArr = new int[array.length];
int t = i;
for(k=i,j=center+1; i<=center && j<=n; k++){
if(array[i]<array[j]){
tmpArr[k] = array[i++];
}
else{
tmpArr[k] = array[j++];
}
}
while(i<=center){
tmpArr[k++] = array[i++];
}
while(j<=n){
tmpArr[k++] = array[j++];
}
while(t<=n)
array[t] = tmpArr[t++];
}
/**
* 非递归实现归并排序
* @param array
*/
public void MergeSort2(int array[]){
int size=1,low,mid,high;
while(size<=array.length-1)
{
low=0;
while(low+size<=array.length-1)
{
mid=low+size-1;
high=mid+size;
if(high>array.length-1)//第二个序列个数不足size
high=array.length-1;
Merge(array,low,mid,high);//调用归并子函数
low=high+1;//下一次归并时第一关序列的下界
}
size*=2;//范围扩大一倍
}
}
快排:选择一个枢轴值,将比其小的放在面前,比其大的放在后面。
/**
* 快排
* @param array
*/
void qucikSort(int[]a,int low,int high){
int key = 0;
if(low<=high){
key = getkey(a,low,high);
qucikSort(a, low, key-1);
qucikSort(a, key+1, high);
}
}
int getkey(int[]a,int s,int e){
int tmp = a[s];
while(s<e){
while(s<e&&a[e]>tmp){
e--;
}
Swap(a, s, e);
while(s<e&&a[s]<tmp){
s++;
}
Swap(a, s, e);
}
return s;
}