[Java]排序算法专题(更新未完)

8 篇文章 0 订阅
4 篇文章 0 订阅

直接上代码思想都在注释里,领悟都在代码中。

public class  Sort
{
	//插入排序
	//思想:不是假定,是真的i前面部分变成有序,通过一步步插入方式排好的序,循环的是要找位置插入的剩余元素!!
	public static int[] insertionSort(int[] A,int n){
		int i,j,temp;
		for(i=1;i<n;i++){
			temp=A[i];
			j=i-1;
			while(j>=0){
				if(temp<A[j]){
					A[j+1]=A[j];
				}else{
					break;//必须结束循环!因为找到这个位置了!!
				}
				j--;
			}
			A[j+1]=temp;
		}
		return A;
	}

	//选择排序
	//思想:遍历,每次选一个最小的,前面i个通过寻找最小值排好序
	public static int[] selectionSort(int[] A,int n){
		for(int i=0;i<n;i++){
			int min=i;//排好序部分的末尾
			for(int j=i+1;j<n;j++){
				if(A[j]<A[min]){
					min=j;
				}
			}
			//注意交换a[i]和a[min]使剩余序列的最小元素交-换-到已排序部分末尾
			int temp=A[min];
			A[min]=A[i];
			A[i]=temp;
		}
		return A;
	}

	//冒泡排序
	//思想:每次遍历,如果相邻元素逆序,交换,这样最大的出现在末尾,以此从尾部削减每次遍历元素数
	//要想最小的元素出现的起始,那得从后往前遍历,也是小在前大在后
	public static int[] bubbleSort(int[] A,int n){
		for(int i=0;i<n-1;i++){
			for(int j=0;j<n-i-1;j++){//每次后面的部分已排好序
				if(A[j]>A[j+1]){
					int temp=A[j];
					A[j]=A[j+1];
					A[j+1]=temp;
				}
			}
		}
		return A;
	}

	//优化1
	//思想:设置一个标记,每次遍历初始都设为false,如果某一趟发生了哪怕一次交换就置为true,以此为判断条件,如果到了某一趟没有一次交换,标记为false,那么提前结束循环!!
	public static int[] bubbleSort2(int[] A,int n){
		boolean flag;
		flag=true;
		while(flag){//外层循环是通过flag控制的,每次缩小规模是靠n--
			flag=false;
			for(int j=0;j<n-1;j++){
				if(A[j]>A[j+1]){
					int temp=A[j];
					A[j]=A[j+1];
					A[j+1]=temp;
					flag=true;
				}
			}
			n--;
		}
		return A;
	}

	//优化2
	//思想:每次遍历,缩小规模的尺度。每次记住最后发生交换的位置,那么这位置后面的都已经有序了,直接跳到该位置!!
	public static int[] bubbleSort3(int[] A,int n){
		int k;
		int flag;//每次最后交换发生的位置

		flag=n;//初始设置为n
		while(flag>0){//以flag>0判断!!
			k=flag;//k每次跳-跃-缩-减-规-模,至上一次flag记录(其后的元素因为再没发生交换而说明已经排序)
			flag=0;
			for(int j=0;j<k-1;j++){
				if(A[j]>A[j+1]){
					int temp=A[j];
					A[j]=A[j+1];
					A[j+1]=temp;
					flag=j+1;//记录最后交换的下标!!
				}
			}
		}
		return A;
	}

	//希尔排序
	//思想:以一组增量多次分组,最后是增量为1每组一个元素,即要排序的序列本身。组元素个数逐步缩减为1,
	//不是组内元素进行排序,而是组内的每个元素以组元素个数为跳跃(增量),在组间插入排序。根据书,排序后的顺序不变,组元素个数逐步缩减为1时,每个元素都排序了。
	public static int[] shellSort1(int A[],int n){
		int i,j,gap;

		for(gap=n/2;gap>0;gap/=2){//增量序列,每次以此为增量分组,直至每组元素个数为1
			for(i=0;i<gap;i++){//第一组中的元素,gap个元素中的每一个都需要以gap为步长,在组间进行插入排序
				for(j=i+gap;j<n;j+=gap){//gap才是步长!对第一组中的元素以gap为增量在整个序列范围寻找元素进行插入排序
					if(A[j]<A[j-gap]){
						//这里才到了为单个元素寻找位置(当然,是以gap为步长)的插入排序,while循环是寻找位置
						int temp=A[j];
						int k=j-gap;
						while(k>=0 && A[k]>temp){
							A[k+gap]=A[k];
							k-=gap;
						}
						A[k+gap]=temp;
					}
				}
			}
		}
		return A;
	}

	//希尔排序:书上的和网上所谓改进的做法
	//思想:第一组以后的每个元素以gap为步长插入到合适的位置,相当于网上两个内循环的第一组的每个元素以gap为步长进行插入排序!!
	public static int[] shellSort2(int A[],int n){
		int i,j,gap;

		for(gap=n/2;gap>0;gap/=2){
			for(i=gap;i<n;i++){
				int temp=A[i];
				for(j=i;j>=gap && temp<A[j-gap];j-=gap)//以gap为步长,挪元素找位置
					A[j]=A[j-gap];
				A[j]=temp;
			}
		}
		return A;
	}

	public static String arrayToString(int[] A){
		StringBuilder builder=new StringBuilder();
		builder.append('[');
		for(int i=0;i<A.length;i++){
			if(i>0)
				builder.append(',');
			builder.append(A[i]);
		}
		builder.append(']');
		return builder.toString();
	}

	public static void main(String[] args) 
	{
		int[] A={2,456,4,576,2235,8,235,87,323,976,24,8,2,1,87,569};
		System.out.println(arrayToString(insertionSort(A,A.length)));
		System.out.println(arrayToString(selectionSort(A,A.length)));
		System.out.println(arrayToString(bubbleSort(A,A.length)));
		System.out.println(arrayToString(bubbleSort2(A,A.length)));
		System.out.println(arrayToString(bubbleSort3(A,A.length)));
		System.out.println(arrayToString(shellSort1(A,A.length)));
		System.out.println(arrayToString(shellSort2(A,A.length)));
	}
}

测试结果:

D:\java\practice9>javac Sort.java

D:\java\practice9>java Sort
[1,2,2,4,8,8,24,87,87,235,323,456,569,576,976,2235]
[1,2,2,4,8,8,24,87,87,235,323,456,569,576,976,2235]
[1,2,2,4,8,8,24,87,87,235,323,456,569,576,976,2235]
[1,2,2,4,8,8,24,87,87,235,323,456,569,576,976,2235]
[1,2,2,4,8,8,24,87,87,235,323,456,569,576,976,2235]
[1,2,2,4,8,8,24,87,87,235,323,456,569,576,976,2235]
[1,2,2,4,8,8,24,87,87,235,323,456,569,576,976,2235]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值