1、插入排序-改进
插入排序每次和前边的比较时,如果小于前边就会每次都交换。可是设置一个变量获取第n个数字,然后进行比较,如果逆序则让n-1的下标+1;直至不满足条件时,再将获取的变量赋给对应的位置,这样可以减少交换的次数,代码如下。
int[] a= {3,4,2,5,1};
int j,t;
for(int i=1 ; i < a.length ; i++){//从第二个下标开始,共循环length-1次
t=a[i];//获取第i个值
for( j = i ; j > 0 ; j - - ){//与前边的值进行比较,逆序则将前一个位置向后移动一次
if(t<a[j-1]){ a[j]=a[j-1]; }
else{ break; }//不满足则返回。
}a[j]=t;//根据获取到的实际位置将值放进去
}
2、希尔排序
希尔排序是插入排序的缩小增量排序,可以理解为分组插入排序。这个排序的代码还是比较上头的。大致的排序方式我用表格的形式表现。
3 | 6 | 2 | 1 | 7 | 8 | 0 | 4 | 5 |
3 | 6 | 2 | 1 | 7 | 8 | 0 | 4 | 5 |
3 | 6 | 0 | 1 | 5 | 8 | 2 | 4 | 7 |
3 | 6 | 0 | 1 | 5 | 8 | 2 | 4 | 7 |
0 | 1 | 2 | 4 | 3 | 6 | 5 | 8 | 7 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
比如0-8,9个数字组成的数组,先分两组,排序。再多分两组,再排序。以此类推
int[] a = {3,6,2,1,7,8,0,4,5};
for( int i = a.length/2 ; i > 0 ; i / = 2){//每次对半分组,只至分为一组。
for( int j = i ; j < a.length ; j + + ){//插入排序,从每组的第二个下标开始
for(int k = j ; k>= i; k -= i){//从每组的第二个数字开始,每次递减步长,直至第二个数字
if( a[k]<a[k-i] ) { int t=a[k]; a[k]=a[k-i]; a[k-i]=t;} //逆序则交换
}
}
}
3、快速排序
去一个数组中的关建值(可以理解为中值),将数组中小于关建值的放在左边,大于关键值的放在右边,使用递归循环直至循环范围只有一个数。
3 | 6 | 2 | 1 | 7 | 8 | 0 | 4 | 5 |
0 | 6 | |||||||
1 | 3 | |||||||
1 | 0 | 2 | 3 | 7 | 8 | 6 | 4 | 5 |
0 | 1 | 4 | 5 | 7 | 8 | |||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
quicksort(int[ ] a , int left , int right){
int i , j , t , temp;
while( left > right){return ;}//确认循环范围不满足条件返回
i = left ; j = right ; temp = a[left] ;
while( i != j){//当左下标等于右下标时,当前循环结束
while( a[j] > temp && i < j){//当最右边的数字大于关建值时需要左移下标。
j --;
}
while( a[i] <= temp && i<j){//当最左边的值小于等于关建值需要右移下标。
i++;
}
if( a[i] > a[j]){//当左边大于关键值,右边小于时,且左边关建值大于右边,互换位置。
t=a[i]; a[i]=a[j]; a[j]=t;
}
}//循环执行内容,直至两个下标相等为止。
a[left]=a[i];//当循环结束,i为中间值对应的为止,与起始为止交换
a[i]=temp;
quicksort(a,left,i-1);//递归调用当前循环
quicksort(a,i+1,right);
}
4、归并排序
使用递归,将数组拆分两个小组,直至数组只有一个值。依次取两个数组中最小的数字合并,当一个数组为空后,另一数组直接全部取出。
5 | 4 | 8 | 2 | 3 | 7 | 1 | 6 |
5 | 4 | 8 | 2 | 3 | 7 | 1 | 6 |
4 | 5 | 2 | 8 | 3 | 7 | 1 | 6 |
2 | 4 | 4 | 8 | 1 | 3 | 6 | 7 |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
public static void mergeSort(int[] a, int first , int end ,int[] temp){
if(first<nd){//只要数组的长度大于1,就能继续分组直至1
int mid=(first+end)/2;
mergeSort(int[] a, first , mid , temp);//递归分组,每次分组后排序
mergeSort(int[] a, mid+1, end ,temp);
mergeArray(int[] a,first , mid ,end , temp);//合并排序
}
}
public static void mergeArray(int[] a, int first ,int mid , int end , int temp){
int i=first;int m=mid;//第一组 int j=mid+1;int n=end;//第二组 int k=0;//操作temp下标
while(i <= m && j <= n){//当某一组的值取完
if(a[i] <= a[j]){//判断两个序列的对应值,按顺序放入temp数组。
temp[k]=a[i]; i++; k++;//放入后自增
}else{
temp[k]=a[j]; j++; k++;//放入后自增
}
}
while(i<=m){//如果j序列取完后直接将i序列全部放入
temp[k]=a[i]; i++; k++;
}
while(j <= n){//如果i序列取完后直接将j序列全部放入
temp[k]=a[j]; j++; k++;
}
for(int s=0 ; s<k ; s++){//将temp的值赋给a
a[first+s]=temp[k];//temp数组一直是0开始赋值,a数组需要将起点设置到指定位置。
}
}
5、堆排序
利用堆(二叉树)结构进行排序,子节点的值总是小于父节点的值。
public static void main(String args[]){
int[] a={4,5,3,7,6,8,1};
heapSort(a);
System.out.print(Arrays.toString(a));
}
public static void heapSort(int[] arr){
for(int i=arr.length/2-1;i>=0;i--){//第一遍将整个树排序
adjustHeap(arr,i,arr.length);
}
for(int j=arr.length-1;j>0;j--){
swap(arr,0,j);//将第一个和未排序的最后一个交换位置
adjustHeap(arr,0,j);//交换排序
}
}
public static void swap(int[] arr,int a,int b){//交换方法
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
public static void adjustHeap(int[] arr,int i,int len){
int temp=arr[i];
for(int k=i*2+1;k<len;k=k*2+1){//根据2*节点下标+1,获取子节点
if(k+1<len&&arr[k]<arr[k+1]){//将两个子节点大的下标赋给k
k++;
}
if(temp<arr[k]){//如果子节点较大的比节点大则交换
arr[i]=arr[k];
i=k;
}else{//否则返回
break;
}
}
arr[i]=temp;
}