java实现部分常见排序算法

17 篇文章 0 订阅

java实现部分常见排序算法

希尔排序
选定步长,将步长间距的几个数进行比较排序,然后初始位后移一位,同样还是将步长间距的几个数进行比较排序,这样的话比较的几个数就是第一次的每个数的后一个数。然后步长就变小,同样进行前面的比较。

package example;

public class ShellSort {
	
	public static void main(String[] args) {
		  int[] arr = {5, 1, 7, 3, 1, 6, 9, 4};
	        shellSort(arr);

	        for (int i : arr) {
	            System.out.print(i + "\t");
	        }
	}
	  private static void shellSort(int[] arr) {
	        //step:步长
	        for (int step = arr.length / 2; step > 0; step /= 2) {//步长的变化依次变小
	            //对一个步长区间进行比较 [step,arr.length)
	            for (int i = step; i < arr.length; i++) {//固定步长下的隔步长距离的比较,i+即后移一位的另一步长组的比较
	                int value = arr[i];
	                int j;
	                //对步长区间中具体的元素进行比较
	                for (j = i - step; j >= 0 && arr[j] > value; j -= step) {//固定步长的数据大的依次后移
	                    //j为左区间的取值,j+step为右区间与左区间的对应值。
	                    arr[j + step] = arr[j]; 
	                }
	                //此时step为一个负数,[j + step]为左区间上的初始交换值
	                arr[j + step] = value;  
	            }
	        }
	    }
	  
	
}

选择排序
和冒泡类似的两次循环,每次循环找到最小的那个数,然后下次循环,冒泡是找到最大的那个,就我个人感觉差不多。

package example;

public class SelectSort {
	
	public static int[] selectSort(int[] arr,int n) {
		for (int i = 0; i < n - 1; i++) {//外循环是趟数,每一趟就位置加一
            int index = i;
            int j;
            // 找出最小值得元素下标
            for (j = i + 1; j < n; j++) {//内循环是每一趟一个元素与其他元素的每一次比较
                if (arr[j] < arr[index]) {
                    index = j;//每次将小的赋给index,循环结束后index就是最小的
                }
            }
            int tmp = arr[index];
            arr[index] = arr[i];
            arr[i] = tmp;//将找到的数赋给外循环的那个循环位置
		}
		return arr;
	}
	public static void main(String[] args) {
		int[] arr={12,3,23,2,3,2314,23,45,3425,34,53,45,4,65,7,56,786,78,34};
		arr=selectSort(arr,arr.length);
		for (int i : arr) {
		System.out.println(i);	
		}
	}
}

RSA案例

package example;

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

public class RSADemo {
	private static String  src="infcn";
		private static RSAPublicKey rsaPublicKey;
		private static RSAPrivateKey rsaPrivateKey;
		
		static{
			KeyPairGenerator keyPairGenerator;
			try {
				keyPairGenerator=KeyPairGenerator.getInstance("RSA");
				keyPairGenerator.initialize(512);
				KeyPair keyPair=keyPairGenerator.generateKeyPair();
				rsaPublicKey=(RSAPublicKey) keyPair.getPublic();
				rsaPrivateKey=(RSAPrivateKey)keyPair.getPrivate();
				System.out.println("Public key:"+Base64.encode(rsaPublicKey.getEncoded()));
				System.out.println("Private key:"+Base64.encode(rsaPrivateKey.getEncoded()));
			} catch (NoSuchAlgorithmException e) {
				// TODO: handle exception
				e.printStackTrace();
			}  			
		}
		
		/**公钥加密,私钥解密
		 * @author 29284
		 * @throws NoSuchAlgorithmException 
		 * @throws InvalidKeySpecException 
		 * @throws NoSuchPaddingException 
		 * @throws InvalidKeyException 
		 * @throws BadPaddingException 
		 * @throws IllegalBlockSizeException 
		 */
		public static  void  pubEn2PriDe() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
			//公钥加密
			X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
			KeyFactory keyFactory=KeyFactory.getInstance("RSA");
			PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
			Cipher cipher=Cipher.getInstance("RSA");
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			byte[] result=cipher.doFinal(src.getBytes());
			System.out.println("公钥加密,私钥解密--加密:"+Base64.encode(result));
			//私钥解密
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
			keyFactory=KeyFactory.getInstance("RSA");
			PrivateKey privateKey=keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			result=cipher.doFinal(result);
			System.out.println("公钥加密,私钥解密--解密:"+new String(result));
			
		}
		
		/**
	     * 私钥加密,公钥解密
	     * @author jijs
		 * @throws NoSuchAlgorithmException 
		 * @throws InvalidKeySpecException 
		 * @throws NoSuchPaddingException 
		 * @throws InvalidKeyException 
		 * @throws BadPaddingException 
		 * @throws IllegalBlockSizeException 
	     */
	    public static void priEn2PubDe() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

	        //私钥加密
	        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
	        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
	        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
	        Cipher cipher = Cipher.getInstance("RSA");
	        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
	        byte[] result = cipher.doFinal(src.getBytes());
	        System.out.println("私钥加密,公钥解密 --加密 : " + Base64.encode(result));

	        //公钥解密
	        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
	        keyFactory = KeyFactory.getInstance("RSA");
	        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
	        cipher = Cipher.getInstance("RSA");
	        cipher.init(Cipher.DECRYPT_MODE, publicKey);
	        result = cipher.doFinal(result);
	        System.out.println("私钥加密,公钥解密   --解密: " + new String(result));
	        }
		public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
			pubEn2PriDe();
			priEn2PubDe();
		}
}

快排
使用快速排序,首先选取数组中某个元素t,然后将其他元素重新排列,使数组中所有在t前面的元素都小于或等于t,所有在t后面的元素都大于或等于t。这里我们使用最简单的选择策略:每次都选取数组第一个元素当做中轴(即前面的t),然后同时从左右开始扫描,左边找到一个比中轴大的,右边找到一个比中轴小的,然后交换两个元素的位置。,然后就是每次都进行同样的过程,这就类似与分治,左边的一部分,右边的一部分。

public static int partition(int[] arr,int left,int right){
        int pivot = arr[left];
        while(left < right){
            while(left<right && arr[right] >= pivot)
                right--;
            arr[left] = arr[right];
            while(left < right && arr[left]<= pivot)
                left++;
            arr[right] = arr[left];
        }
        arr[left] = pivot;
        return left;
    }

插入排序
插入排序就是首先认为数组已经是有序了的,先找到一个数放入,然后依次将下一个数与他们进行比较找到合适的位置插进去,每次插入后数组都是有序的。

package example;
public class InsertSort{
    public static int[] insertSort(int[] arr)
    {
        for (int i = 1; i < arr.length; i++)//每次选择一个插入
        {
            int k = arr[i];//k用来代替arr【i】进行大小判断
            int j = i;//j内循环用来判断当前位与前一位的大小
            while (j > 0 && arr[j - 1] > k)//如果要插入的元素的前一位比他大则前一位后移
            {
                arr[j] = arr[j - 1];//元素后移
                j--;//变量前移
            }
            arr[j] = k;//k插入到这
       }
        return arr;
    }
		public static void main(String[] args) {
			int[] arr={1,23,3,44,5,4,56,57,6,7,568,67,89,67,986,7,6,79,23,86,78,6,8};
			arr=insertSort(arr);
			for (int i : arr) {
				System.out.println(i);
			}
		}
}

冒泡排序
这个最简单就没得什么说的了

 @Test
    void test15() {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(10);
        list.add(5);
        list.add(17);
        list.add(6);
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j <list.size()-i-1; j++) {
                if (list.get(j).compareTo(list.get(j+1))>0) {
                    Integer temp = list.get(j);
                    list.set(j,list.get(j+1));
                    list.set(j+1,temp);
                }

            }
        }
        list.stream().forEach(e-> System.out.println(e));
    }

线程池

package example.testForJava;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class threadPool {
    public static void main(String[] args) {
        //线程池容量为5,最大可扩展到10
        /*保持200表示线程没有任务执行时最多保持多久时间会终止。
         默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,
         直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,
         如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。
        unit为前一参数的单位*/
        //等待队列
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(5));
        for (int i = 0; i < 15; i++) {
            MyTask myTask = new MyTask(i);
            executor.execute(myTask);
            System.out.println("thread pool num " + executor.getPoolSize() + "  queue num " + executor.getQueue().size() + " already complected num " + executor.getCompletedTaskCount());
        }
        executor.shutdown();
    }
}

基数排序

基数排序介绍
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用
基数排序法是属于稳定性的排序,基数排序法是效率高的稳定性排序法。

LSD
排序过程就是先将一组数以个位数的顺序排列后,再将得到的序列按十位数的顺序排列,再依次往高位移动,最后得到数列。适用与位数较小的序列。

MSD
位数多的话用次方法,由高位开始,但是分配后并不马上合并回一个数组中,而是在每个桶中建立子桶,每个桶中按下一位分配到桶,在进行完最低位数的分配后再合并回单一的数组中

//LSD
public class RadixSort {
    public static void main(String[] args) {
    int arr[]={53, 3, 542, 748, 14, 214};
    radixSort(arr);
    }

    public static void  radixSort(int[] arr){
        //先求出数组中的最大的数
        int max=arr[0];
        for(int i=1;i<arr.length;i++){
            if(arr[i]>max){
                max=arr[i];
            }
        }
        //得到最大数是几位数
        int maxLength=(max+"").length();

        //定义一个二维数组,表示10个桶,每个桶就是一个数组
        //为了在放入数时防止数据溢出,我们每个桶的大小为arr.length,即每个桶最多放进数组里的所有元素
        int[][] bucket=new int[10][arr.length];

        //定义一个一维数组来记录各个桶的每次放入的数据个数
        int[] bucketElementCount=new int[10];

        for(int i=0,n=1;i<maxLength;i++,n*=10){
            //对每个元素的对应位进行处理
            for(int j=0;j<arr.length;j++){
                //取出每个元素的对应位的值
                int digiOfElement=arr[j]/n%10;
                //放入到对应的桶中
                bucket[digiOfElement][bucketElementCount[digiOfElement]]=arr[j];
                bucketElementCount[digiOfElement]++;
            }
            //按照这个桶的顺序即一维数组的下标一次取出数据放入原来数组
            int index=0;
            //遍历每一桶,并将桶中数据放入到原数组
            for(int k=0;k<bucketElementCount.length;k++){
                //如果桶中有数据,才放入原来数组
                if(bucketElementCount[k]!=0){
                    for(int m=0;m<bucketElementCount[k];m++){
                        arr[index++]=bucket[k][m];
                    }
                }
                //每一轮处理后,需将bucketElementCount[k]=0
                bucketElementCount[k]=0;
            }
            System.out.println("第"+(i+1)+"轮,对个位数的排序处理 arr="+ Arrays.toString(arr));
        }

    }

}

合并排序(归并排序)使用分治思想
每次就将一个大数组分成两个小数组,然后递归调用,直到最后只剩一个数,就是排好序的,然后就递归回去,每次将已经排好序的两个小数组合并成一个大数组。分后的图就类似于一个二叉树。

void Copy(int a[],int b[],int left,int right)
{
    //将b[0]至b[right-left+1]拷贝到a[left]至a[right]
	int size=right-left+1;
	for(int i=0; i<size; i++) {
		a[left++]=b[i];
	}
}
void Merge(int a[],int b[],int left,int i,int right)
{
    //合并有序数组a[left:i],a[i+1:right]到b,得到新的有序数组b
	int a1cout=left, //指向第一个数组开头
	    a1end=i, //指向第一个数组结尾
	    a2cout=i+1, //指向第二个数组开头
	    a2end=right, //指向第二个数组结尾
	    bcout=0; //指向b中的元素
	for(int j=0; j<right-left+1; j++) {
        //执行right-left+1次循环,数组
		if(a1cout>a1end) {
			b[bcout++]=a[a2cout++];
			continue;
		}  //如果第一个数组结束,拷贝第二个数组的元素到b
		if(a2cout>a2end) {
			b[bcout++]=a[a1cout++];
			continue;
		}  //如果第二个数组结束,拷贝第一个数组的元素到b
		if(a[a1cout]<a[a2cout]) {
			b[bcout++]=a[a1cout++];
			continue;
		}  //如果两个数组都没结束,比较元素大小,把较小的放入b
		else {
			b[bcout++]=a[a2cout++];
			continue;
		}
	}
}
void MergeSort(int a[],int left,int right)
{
    //对数组a[left:right]进行合并排序
	int *b=new int[right-left+1];
	if(left<right) {
		int i=(left+right)/2;//取中点
		MergeSort(a,left,i);//左半边进行合并排序
		MergeSort(a,i+1,right);//右半边进行合并排序
		Merge(a,b,left,i,right);//左右合并到b中
		Copy(a,b,left,right);//从b拷贝回来
	}
}
int main()
{
	int n=10;
	int a[]={5,8,2,9,4,6,3,1,10,7};
	MergeSort( a, 0, n-1);
	for(int j=0; j<n; j++) {
		cout<<" "<<a[j];
	}
	return 1;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

菜鸟程序员李老板专业码代码三十年

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

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

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

打赏作者

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

抵扣说明:

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

余额充值