java7种排序算法和速度

附加java源码包下载地址

冒泡排序

package paixu;

import java.util.Random;
/*
 * 冒泡排序
 * 时间复杂度:平均O(n^2),最坏O(n^2)
 * */
public class maopao {
	public static void main(String[] args){
		long start=System.currentTimeMillis(); //获取开始时间  
		int arr[]=new int[20000];
		//设置一个数组长度为20000,然后往里面随机赋值0~20000的数字
		for(int i=0;i<20000;i++){
			Random random = new Random();
			arr[i]=	random.nextInt(20000);
		}
		//冒泡排序算法
		for(int i=1;i<arr.length;i++){
			for(int j=0;j<arr.length-i;j++){
				if(arr[j]>arr[j+1]){		
					int temp=arr[j];
					arr[j]=arr[j+1];
					arr[j+1]=temp;
				}
			}
		}
		//输出结果
		for(int i=0;i<arr.length;i++){
			if(i!=arr.length-1)
				System.out.print(arr[i]+",");
			else
				System.out.println(arr[i]);
		}
		long end=System.currentTimeMillis(); //获取结束时间 
		System.out.println("程序运行时间: "+(end-start)+"ms");

	}
}

运行结果

程序运行时间: 558ms

插入排序

package paixu;

import java.util.Random;
/*
 * 插入排序
 * 时间复杂度:平均O(n^2),最坏O(n^2)
 * */
public class charu {
	public static void main(String[] args){
		long start=System.currentTimeMillis(); //获取开始时间  
		int arr[]=new int[20000];
		//设置一个数组长度为20000,然后往里面随机赋值0~20000的数字
		for(int i=0;i<20000;i++){
			Random random = new Random();
			arr[i]=	random.nextInt(20000);
		}
		//插入排序算法
		int j, temp;
		for (int i = 1; i < arr.length; i++) {// 从数组的第二个元素开始循环将数组中的元素插入
			temp = arr[i];// 设置数组中的第2个元素为第一次循环要插入的数据
			j = i - 1;
			while (j >= 0 && temp < arr[j]) {
				arr[j + 1] = arr[j];// 如果要插入的元素小于第j个元素,就将第j个元素向后移动
				j--;
			}
			arr[j + 1] = temp;// 直到要插入的元素不小于第j个元素,将temp插入到数组中
		}
		//输出结果
		for(int i=0;i<arr.length;i++){
			if(i!=arr.length-1)
				System.out.print(arr[i]+",");
			else
				System.out.println(arr[i]);
		}
		long end=System.currentTimeMillis(); //获取结束时间 
		System.out.println("程序运行时间: "+(end-start)+"ms");
	}
}


运行结果

程序运行时间: 188ms

希尔排序

package paixu;

import java.util.Random;
/*
 * 希尔排序
 * 平均O(n^1.5),最坏O(n^2)
 * */
public class xier {
	public static void main(String[] args){
		long start=System.currentTimeMillis(); //获取开始时间  
		int arr[]=new int[20000];
		//设置一个数组长度为20000,然后往里面随机赋值0~20000的数字
		for(int i=0;i<20000;i++){
			Random random = new Random();
			arr[i]=	random.nextInt(20000);
		}
		//希尔排序算法
		int incrementNum=arr.length/2;
		for (int increment = incrementNum; increment > 0; increment /= 2) {
			//下面就是一个修改过的插入排序
			for (int i = increment; i < arr.length; i++) {
				if(arr[i] < arr[i-increment]){
					int temp = arr[i];
					int j;
					for(j = i-increment; j >= 0 && arr[j] > temp; j -=increment){
						arr[j+increment] = arr[j];
					}
					arr[j+increment] = temp;
				}
			}
		}
		//输出结果
		for(int i=0;i<arr.length;i++){
			if(i!=arr.length-1)
				System.out.print(arr[i]+",");
			else
				System.out.println(arr[i]);
		}
		long end=System.currentTimeMillis(); //获取结束时间 
		System.out.println("程序运行时间: "+(end-start)+"ms");

	}
}

具体可以看https://www.cnblogs.com/chengxiao/p/6104371.html

运行结果

程序运行时间: 83ms

快速排序

package paixu;

import java.util.Random;

public class kuaisu {
	public static void main(String[] args){
		long start=System.currentTimeMillis(); //获取开始时间  
		int arr[]=new int[20000];
		//设置一个数组长度为20000,然后往里面随机赋值0~20000的数字
		for(int i=0;i<20000;i++){
			Random random = new Random();
			arr[i]=	random.nextInt(20000);
		}
		//快速排序算法
		quickSort(arr,0,arr.length-1);
		//输出结果
		for(int i=0;i<arr.length;i++){
			if(i!=arr.length-1)
				System.out.print(arr[i]+",");
			else
				System.out.println(arr[i]);
		}
		long end=System.currentTimeMillis(); //获取结束时间 
		System.out.println("程序运行时间: "+(end-start)+"ms");

	}
	public static void quickSort(int[] array,int low,int high){
		int start = low;//开始位置(前端)
		int end = high;//结束位置(后端)
		int key = array[low];//关键值,也就是枢轴。第一次从位置0开始取,一轮排完会后排到中间。

		while(end>start){//
			//现在关键值在“前端”,从后往前比较,要找到小于关键值的值
			//如果比关键值大,则比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
			while(end>start&&array[end]>=key)
				end--;//如果最后一个值大于关键值,则end往前移一位,拿倒数第二个比···

			//由于之前的end--,现在是往前移了一位了,
			// 如果这时候刚好比关键值小,则将小的值和关键值交换位置。
			if(array[end]<=key){
				int temp = array[end];
				array[end] = array[start];
				array[start] = temp;
			}
			//现在关键值在后端,从前往后比较,要找到大于关键值的值
			//如果比关键值小,则比较下一个,直到有比关键值大的交换位置
			while(end>start&&array[start]<=key)

				//从前端开始找,如果前端的值比目前处在后端的关键值小,
				// 则start++,将前端位置往后移一位
				start++;
			//由于前端往后移了一位,就再比一次,
			// 如果此时前端值刚好比关键值大,则交换位置,把关键值交换到前端。
			if(array[start]>=key){
				int temp = array[start];
				array[start] = array[end];
				array[end] = temp;
			}
			//此时第一次循环比较结束,关键值(枢轴)的位置已经确定了。
			// 左边的值都比关键值小,右边的值都比关键值大,
			// 但是两边的顺序还有可能是不一样的,进行下面的递归调用
		}
		//递归,此时分别对枢轴两边进行快排
		//此时low是初始时的开始位置,start则++了好几次,low位至start位构成了左边序列。
		// low作为左边序列的起始位,start其实是枢轴的位置,所以start-1就是左边序列的结束位
		if(start>low) quickSort(array,low,start-1);
		//此时end是枢轴的位置,所以end+1是右边序列的起始位,high是最初的结束为
		// (也就是最后一个数,期间改变的是end,high没变),所以high就是右边序列的结束位
		if(end<high) quickSort(array,end+1,high);
	}
}
运行结果
程序运行时间: 77ms

选择排序

package paixu;

import java.util.Random;

public class xuanze {
	public static void main(String[] args){
		long start=System.currentTimeMillis(); //获取开始时间  
		int arr[]=new int[20000];
		//设置一个数组长度为20000,然后往里面随机赋值0~20000的数字
		for(int i=0;i<20000;i++){
			Random random = new Random();
			arr[i]=	random.nextInt(20000);
		}
		//选择排序算法
		int len=arr.length;
		int small;//一次比较中最小的下标。
		int temp;
		//初始从第0位开始找,此位放最小的数,之后第1位放第二小的数·····
		for(int i=0;i<len-1;i++){
			small=i;//该此比较中最小的下标

			//把假定最小下标后的下标的值与该值循环比较,每次都将更小的下标赋给small,
			// 一轮下来,small里就是真正的最小下标
			for(int j=i+1;j<len;j++){
				//如果找到比“最小下标”小的值,则将该下标改成最小下标
				if(arr[j]<arr[small]){
					small=j;
				}
			}
			//查询一轮下来,判断small是否变更,如果没变就表示目前i位就是最小的,不用换位。否则换位
			if(i!=small){
				//将目前找到的最小元素临时装到temp中
				temp=arr[small];

				//此处没有直接将i位于small位交换,
				// 因为直接交换可能会导致相同的数据元素位置发生变化,引起排序不稳定。

				//将第i位至第samll-1位的元素集体向后移一位
				// (这样就刚好把第samll位盖住了,顺序也不会发生改变,也保证了稳定性)
				for(int k=small;k>i;k--){
					arr[k]=arr[k-1];
				}
				arr[i]=temp;//将目前最小值赋值给第i位
			}
		}
		//输出结果
		for(int i=0;i<arr.length;i++){
			if(i!=arr.length-1)
				System.out.print(arr[i]+",");
			else
				System.out.println(arr[i]);
		}
		long end=System.currentTimeMillis(); //获取结束时间 
		System.out.println("程序运行时间: "+(end-start)+"ms");
	}
}

运行结果

程序运行时间: 201ms

归并

package paixu;

import java.util.Random;
/*
 * 插入排序
 * 时间复杂度:平均O(n^2),最坏O(n^2)
 * */
public class guibing {
	public static void main(String[] args){
		long start=System.currentTimeMillis(); //获取开始时间  
		int arr[]=new int[20000];
		//设置一个数组长度为20000,然后往里面随机赋值0~20000的数字
		for(int i=0;i<20000;i++){
			Random random = new Random();
			arr[i]=	random.nextInt(20000);
		}
		//归并排序算法
		mergingSort(arr,0,arr.length-1);
		//输出结果
		for(int i=0;i<arr.length;i++){
			if(i!=arr.length-1)
				System.out.print(arr[i]+",");
			else
				System.out.println(arr[i]);
		}
		long end=System.currentTimeMillis(); //获取结束时间 
		System.out.println("程序运行时间: "+(end-start)+"ms");
	}

	public static void mergingSort(int[] array, int left, int right){
		if (left<right){
			//找到传入数组的中间位
			int center = (left + right)/2;
			//将中间位作为“左边边界”递归,这样就能不断二分左边数组
			mergingSort(array, left, center);
			//找到和左边数组对应的右边部分
			mergingSort(array, center + 1, right);
			//根据相关数据可以确定需要排序的范围,进行排序
			merge(array, left, center, right);
		}
	}

	/**
	 * 相当于有三个数组:
	 * leftPos到leftEnd组成了第一个待排数组,
	 * rightPos到rightEnd组成了第二个待排数组。
	 * 还有一个空的数组用来临时存储结果。
	 *
	 * 每次将两个待排数组的最靠前项相比较,
	 * 将其中最小的一项放入空数组中,
	 * 然后该最小项所在数组的靠前下标+1
	 *
	 * 即有a[],b[]两个数组比较,
	 * 先比较a[0],b[0],发现a[0]小,就将a[0]放入result[],再比较a[1]和b[0]······
	 *
	 * 其中两个待排数组自身肯定是有序的(因为他们也是经过现有步骤排出来的)
	 *
	 * 当其中某个待排数组排完后,
	 * 就表示“另一个待排数组的剩余项肯定大于之前所有的排序项”,又因为剩余项是有序的,
	 *
	 * 所以可以将剩余项全部按序装入临时结果数组。
	 * 之后用结果数组覆盖掉原数组
	 *
	 * @param array 待排数组
	 * @param leftPos 待排数组的左边部分的起始位
	 * @param leftEnd 待排数组左边部分的结束位
	 * @param rightEnd 待排数组右边部分的结束位
	 */
	private static void merge(int[] array, int leftPos, int leftEnd, int rightEnd) {
		int[] tmpArr = new int[rightEnd+1];//临时的结果数组,将排序后的结果存放其中
		int rightPos = leftEnd + 1;//位于右边的待排数组开始位
		int tmpPos = leftPos; //临时数组的存储位,每存一个,就后移一位
		int tmp = leftPos;//排序的起始位置

		// 从两个数组中取出最小的放入临时数组
		while (leftPos <= leftEnd && rightPos <= rightEnd) {
			if ((array[leftPos] <= array[rightPos])){
				tmpArr[tmpPos++] = array[leftPos++];
			}else {
				tmpArr[tmpPos++] = array[rightPos++];
			}
		}

		//此时肯定有一个待排数组已经排完了,现在查找那个数组排完了,
		// 并将另一个数组的剩余部分装入临时数组
		while (rightPos <= rightEnd) {
			tmpArr[tmpPos++] = array[rightPos++];
		}
		while (leftPos <= leftEnd) {
			tmpArr[tmpPos++] = array[leftPos++];
		}

		// 将临时数组中的内容复制回原数组
		for (int i = tmp; i <= rightEnd; i++) {
			array[i] = tmpArr[i];
		}
	}
}

运行结果

程序运行时间: 241ms

基数排序

package paixu;

import java.util.Random;
/*
 * 插入排序
 * 时间复杂度:平均O(n^2),最坏O(n^2)
 * */
public class jishu {
	public static void main(String[] args){
		long start=System.currentTimeMillis(); //获取开始时间  
		int arr[]=new int[20000];
		//设置一个数组长度为20000,然后往里面随机赋值0~20000的数字
		for(int i=0;i<20000;i++){
			Random random = new Random();
			arr[i]=	random.nextInt(20000);
		}
		//基数排序算法
		radixSort(arr,5);
		//输出结果
		for(int i=0;i<arr.length;i++){
			if(i!=arr.length-1)
				System.out.print(arr[i]+",");
			else
				System.out.println(arr[i]);
		}
		long end=System.currentTimeMillis(); //获取结束时间 
		System.out.println("程序运行时间: "+(end-start)+"ms");
	}



	public static void radixSort(int[] array,int len_max){
		/**
		 * 一般的桶排序的count[]只是一维数组,
		 * 里面的每项(0-9)的具体值代表了该数出现的次数,
		 * 如count[2]=3,代表2这个“项”,出现了3次。
		 *
		 * 但现在是“从个位开始”,每一位都要做桶排序。
		 * 如果还是使用count[],
		 * 那么count[2]=3只能代表“在所有项的第n位桶排序中”2这个数“作为第n位数”出现了3次。
		 *
		 * 显然,正常的流程是:
		 * 先查找“个位”的count[0]=n,将这些“个位为0”的数从第0位开始放入数组。
		 * 再看“个位”的count[1]=m,将这些“个位为1”的数紧挨着刚刚插入的数插进来。·····
		 * “个位”的第一轮排序完后,原数组相当于“依据个位大小,进行了一次排序”,
		 * 接下来就要“依据十位大小再进行一次排序了”····。
		 *
		 * 综上流程能够发现,第n位中count[2]=3,这个2代表了“3个n位为2的数”,
		 * 我们要排序就必须知道“这3个数具体是什么”,然后把这些数按序放入原数组。
		 * 所以引入二维数组count[][],
		 * 第一维的下标代表了该位数“具体是几”,所以范围是0-9。
		 * 第二维的下标代表了该位数相同的值“第几次出现”,
		 * (如个位桶排序时,count[2][34]就代表了第34个“个位为2的数”。)
		 * 第二维中存储的是具体的某个数
		 */
		int[][] count = new int[10][array.length];

		//该数组frequency[n]=m,用来计算“某位的桶排序”中“n这个数第m次出现”。
		// 所以n的范围只能是0-9,而m最多可能是原数组的长度(当该数组某一位的值都是同一个数时)
		int[] frequency = new int[10];

		int now_digit = 1;//当前排序的是各项的第几位数(从第一位(个位)开始排)
		int n = 1;//用来计算当前位的具体值

		//从个位开始排,然后再排十位·····
		while (now_digit<=len_max){
			//根据原数组中各项的“now_digit位”,进行桶排序。
			for (int i=0;i<array.length;i++){
				//找到具体某位的值。如n=1时,找到的就是个位的值。n=10时,找到的就是十位的值
				int digit = ((array[i] / n) % 10);
				count[digit][frequency[digit]]=array[i];
				frequency[digit]++;
			}

			/**
			 * 现在所有的项已经根据桶排序规则存入count[][]中,现在需要按序再存回原数组。思路如下:
			 * count[][]中第一个下标意味着“当前位”的具体值,为0-9.
			 * 所以应该将count[0][n]中的各个数排在前面,count[1][m]中的各项跟在后面·····
			 * count[0][]中存了多个“当前位为0的数”,
			 * 而count[][]的第二个下标表示“被存储的数”是“第几个下标为0的数”。
			 * 如:当前位为“个位”排序时,count[0][1]=21表示21是第一个“个位为0的数”,
			 *    count[0][6]=341表示341是第6个“个位为0的数”
			 */
			//把数据存在原数组的什么位置(起始的存储位置自然是0,然后每存一个数后移一位)
			int k = 0;
			//从count[i=0][]开始找,然后找count[i++][]····
			for(int i = 0; i < 10; i++) {
				//frequency[i]代表了“i这个数第几次出现”,所以为0就表示没出现过,也就不用排了
				if(frequency[i] != 0){
					//从第0次出现开始找,每次都装入原数组
					for(int j = 0; j < frequency[i]; j++) {
						//j代表了“位值为i”的数是第几个,count[i][j]代表了该数
						array[k] = count[i][j];
						k++;
					}
				}
				//“当前位数”为i的数已经存完,需要初始化,否则下一“位数为i”的数存时会出错。
				frequency[i] = 0;
			}
			//每循一次,用来计算当前位的具体值的n做+10处理
			n *= 10;
			//每循一次,当前位数+1
			now_digit++;
		}
	}
}

运行结果

程序运行时间: 74ms

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gentle+

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值