排序算法汇总(JAVA)

插入排序

/*插入排序*/
	//第一步:将第一个数和第二个数排序,然后构成一个有序序列
	//第二步:将第三个数插入进去,构成一个新的有序序列。
	//第三步:对第四个数、第五个数……直到最后一个数,重复第二步。
	public void insertSort(int[] a) {
		int length=a.length;
		int insertNum;
		for(int i=1;i<length;i++)
		{
			insertNum=a[i];  //要插入的数
			int j=i-1;   //已经排序好的序列元素个数
			//序列从后到前循环,将大于InsertNum的数向前移一位
			while (j>=0&&a[j]>insertNum) {
				a[j+1]=a[j];
				j--;
			}
			a[j+1]=insertNum;  //将要插入的数插在这个位置
		}
	}

冒泡排序

/*冒泡排序*/
	//step1:将序列中所有元素两两比较,将最大的放在最后面。
	//step2:将剩余序列中所有元素两两比较,将最大的放在最后面。
	//step3:重复第二步,直到只剩下一个数。
	public void bubbleSort(int[] a) {
		int length=a.length;
		int temp;
		for(int i=0;i<length;i++)
		{
			for(int j=0;j<length-i-1;j++)
			{
				if(a[j]>a[j+1])
				{
					temp=a[j];
					a[j]=a[j+1];
					a[j+1]=temp;
				}
			}
		}
	}

快速排序

/*快速排序*/
	//选择第一个数为p,小于p的数放在左边,大于p的数放在右边。
	//递归的将p左边和右边的数都按照第一步进行,直到不能递归。
	public void quickSort(int[] numbers,int start,int end) {
		if(start<end)
		{
			int base=numbers[start];  //选定的基准值(第一个数作为基准)
			int temp;
			int i=start,j=end;
			do {
				while((numbers[i]<base)&&(i<end))
					i++;
				while((numbers[j]>base)&&(j>start))
					j--;
				if(i<=j)
				{
					temp=numbers[i];
					numbers[i]=numbers[j];
					numbers[j]=temp;
					i++;
					j--;
				}
			} while (i<=j);
			if(start<j)
				quickSort(numbers, start, j);
			if(end>i)
				quickSort(numbers, i, end);
		}
	}
	

归并排序

/*归并排序*/
	//将两个有序的数组归并成一个更大的有序数组。
	//采用分治(divide and conquer)策略,
	//利用递归每次将数组分成两半,
	//直到子数组个数为1(1个元素的数组自然就有序的),
	//将结果归并再返回。
	public void mergeSort(int[] arr,int left,int right) 
	{
		if(left<right) {
			int mid=(left+right)/2;
			//左边归并排序,使得左子序列有序
			mergeSort(arr, left, mid);  
			//右边归并排序,使得右子序列有序
			mergeSort(arr, mid+1, right);
			//合并两个子序列
			merge(arr, left, mid, right);
			
		}
	}
	private void merge(int[] arr,int left,int mid,int right) {
		int[] temp=new int[right-left+1];
		int i=left;
		int j=mid+1;
		int k=0;
		while(i<=mid&&j<=right)
		{
			if(arr[i]<arr[j]){
				temp[k++]=arr[i++];
			}
			else {
				temp[k++]=arr[j++];
			}
		}
		//将左边剩余元素填充进temp中
		while(i<=mid) {
			temp[k++]=arr[i++];
		}
		//将右边剩余元素填充进temp中
		while(j<=right) {
			temp[k++]=arr[j++];
		}
		//将temp中的元素全部拷贝到原数组中
		for(int k2=0;k2<temp.length;k2++)
		{
			arr[k2+left]=temp[k2];
		}
	}
	

简单选择排序

/*简单选择排序*/
	//遍历整个序列,将最小的数放在最前面。
	//遍历剩下的序列,将最小的数放在最前面。
	//重复第二步,直到只剩下一个数。
	public void selectSort(int[] a) 
	{
		int length=a.length;
		for(int i=0;i<length;i++)
		{
			int key=a[i];
			int position=i;
			for(int j=i+1;j<length;j++)
			{
				if(a[j]<key)
				{
					key=a[j];
					position=j;
				}
			}
			a[position]=a[i];  //交换位置
			a[i]=key;
		}
	}

堆排序

参考文章
https://www.cnblogs.com/skywang12345/p/3602162.html

	/*堆排序(从小到达)*/
	//将序列构建成大顶堆。
    //将根节点与最后一个节点交换,然后断开最后一个节点。
    //重复第一、二步,直到所有节点断开。
	public void heapSortAsc(int[] a)
	{
		int i,temp;
		int length=a.length;
		//从(length/2-1)--->0逐次遍历。遍历后后得到的是一个最大二叉堆
		for(i=length/2-1;i>=0;i--)
		{
			maxHeapDown(a,i,length-1);
		}
		// 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
		for(i=length-1;i>0;i--)
		{
			temp=a[0];
			a[0]=a[i];
			a[i]=temp;
			// 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
			// 即,保证a[i-1]是a[0...i-1]中的最大值。
			maxHeapDown(a, 0, i-1);
		}
		
	}
	/* 
	 11      * (最大)堆的向下调整算法
	 12      *
	 13      * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
	 14      *     其中,N为数组下标索引值,如数组中第1个数对应的N为0。
	 15      *
	 16      * 参数说明:
	 17      *     a -- 待排序的数组
	 18      *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
	 19      *     end   -- 截至范围(一般为数组中最后一个元素的索引)
	 20      */
	private void maxHeapDown(int[] a,int start,int end)
	{
		int c=start;
		int l=2*c+1;
		int temp=a[c];
		for(;l<=end;c=l,l=2*l+1)
		{
			 // "l"是左孩子,"l+1"是右孩子
			if(l<end&&a[l]<a[l+1])
				l++;   // 左右两孩子中选择较大者,即m_heap[l+1]
			if(temp>=a[l])
				break; // 调整结束
			else {     // 交换值
				a[c]=a[l]; 
				a[l]=temp;
			}
		}
	}

希尔排序

参考文章
https://blog.csdn.net/qq_37592492/article/details/81157153

	//希尔排序
	//将数的个数设为n,取奇数k=n/2,将下标差值为k的书分为一组,构成有序序列。
    //再取k=k/2 ,将下标差值为k的书分为一组,构成有序序列。
	//重复第二步,直到k=1执行简单插入排序。
	public void shellSort(int[] a)
	{
		int length=a.length;
		//gap为步长,每次减少为原来一般
		for(int gap=length/2;gap>0;gap=gap/2)
		{
			//共gap个组,每一组都执行直接插入排序
			for(int i=0;i<gap;i++)
			{
				//插入排序
				for(int j=i+gap;j<length;j+=gap)
				{
					//如果a[j]<a[j-gap],则寻找a[j]的位置
					//并将后面的数据位置后移
					if(a[j]<a[j-gap])
					{
						int temp=a[j];
						int k=j-gap;
						while(k>=0&&a[k]>temp)
						{
							a[k+gap]=a[k];
							k=k-gap;
						}
						a[k+gap]=temp;
					}
				}
			}
		}
	}

基数排序

参考文章
https://blog.csdn.net/qq_42857603/article/details/82351864

	/*基数排序*/
	//将所有的数的个位数取出,按照个位数进行排序,构成一个序列。
	//将新构成的所有的数的十位数取出,按照十位数进行排序,构成一个序列。
	//依次类推
	public void radixSort(int[] a) 
	{
		//求最大位数
		int k=getNumberCount(getMax(a));
		
		//count数组用来计数
		int[] count=new int[10];
		//bucket用来当桶
		int[] bucket=new int[a.length];
		
		//m表示第几位,1代表个位,2代表十位
		for(int m=1;m<=k;m++)
		{
			//把count置空,防止上次循环数据的影响
			for(int i=0;i<10;i++)
			{
				count[i]=0;
			}
			
			//分别统计第k位是0,1,2,3,4,5,6,7,8,9的数量
			//即此循环用来统计每个桶中的数据的数量
			for(int i=0;i<a.length;i++)
			{
				count[getFigure(a[i], m)]++;
			}
			
			//利用count[i]来确定放置数据的位置
			for(int i=1;i<10;i++)
			{
				count[i]=count[i]+count[i-1];
			}
			//执行完此循环之后的count[i]就是第i个桶右边界的位置
			
			//利用循环把数据装入各个桶中,注意是从后往前装
			for(int i=a.length-1;i>=0;i--)
			{
				int j=getFigure(a[i], m);
				bucket[count[j]-1]=a[i];
				count[j]--;
			}
			
			//将桶中数据取出来,赋值给a
			for(int i=0;i<a.length;i++)
			{
				a[i]=bucket[i];
			}	
		}
		
	}
	private int getFigure(int a,int m)
	{
		int h=(int)Math.pow(10, m-1);
		return (a/h)%10;
	}
	private int getNumberCount(int maxNum)
	{
		int num=1;
		int t=maxNum/10;
		while(t!=0)
		{
			num++;
			t=t/10;
		}
		return num;
	}
	private int getMax(int[] a)
	{
		int max=a[0];
		for(int i=1;i<a.length;i++)
		{
			if(a[i]>max)
			{
				max=a[i];
			}
		}
		return max;
	}

计数排序

/**
 * 计数排序
 */
public class CountSort {
    public static int[] countSort(int[] array){
        //得到数列的最大值和最小值,并算出差值
        int max=array[0];
        int min=array[0];
        for(int i=0;i<array.length;i++){
            if(array[i]>max)
                max=array[i];
            if(array[i]<min)
                min=array[i];
        }
        int d=max-min;
        //创建统计数组并统计对应元素的个数
        int[] countArray=new int[d+1];
        for(int i=0;i<array.length;i++){
            countArray[array[i]-min]++;
        }

        //3统计数组做变形,后面的元素等于前面的元素之和
        for(int i=1;i<countArray.length;i++){
            countArray[i]+=countArray[i-1];
        }

        //倒序遍历原始数组,从统计数组中找到正确位置,输出到结果数组
        int[] sortedArray=new int[array.length];
        for(int i=array.length-1;i>=0;i++){
            sortedArray[countArray[array[i]-min]-1]=array[i];
            countArray[array[i]-min]--;
        }
        return sortedArray;
    }
}

桶排序

import java.util.*;

public class bucketSort {
    public static double[] bucketSort(double[] array){
        //得到数列的最大值和最小值,并算出差值d
        double max=array[0];
        double min=array[0];
        for(int i=1;i<array.length;i++){
            if(array[i]>max)
                max=array[i];
            if(array[i]<min)
                min=array[i];
        }

        double d=max-min;
        //初始化桶
        int bucketNum=array.length;
        ArrayList<LinkedList<Double>> bucketList=new ArrayList<LinkedList<Double>>(bucketNum);
        for(int i=0;i<bucketNum;i++){
            bucketList.add(new LinkedList<Double>());
        }

        //遍历原始数组,将每个元素放入桶中
        for(int i=0;i<array.length;i++){
            int num=(int)((array[i]-min)*(bucketNum-1)/d);
            bucketList.get(num).add(array[i]);
        }

        //对每个桶类别进行排序
        for(int i=0;i<bucketList.size();i++){
            Collections.sort(bucketList.get(i));
        }

        //输出全部元素
        double[] sortedArray=new double[array.length];
        int index=0;
        for(LinkedList<Double> list:bucketList){
            for(double ele:list){
                sortedArray[index]=ele;
                index++;
            }
        }
        return sortedArray;
    }

    public static void main(String[] args) {
        double[] array=new  double[]{4.12,3.14,3.56,4.32,5.89,9.02};
        double[] sortedArray=bucketSort(array);
        System.out.println(Arrays.toString(sortedArray));
    }
}

总结

不稳定:

  选择排序(selection sort)— O(n2)

  快速排序(quicksort)— O(nlogn) 平均时间, O(n2) 最坏情况; 对于大的、乱序串列一般认为是最快的已知排序

  堆排序 (heapsort)— O(nlogn)

  希尔排序 (shell sort)— O(nlogn)

  基数排序(radix sort)— O(n·k); 需要 O(n) 额外存储空间 (K为特征个数)

稳定:

  插入排序(insertion sort)— O(n2)

  冒泡排序(bubble sort) — O(n2)

  归并排序 (merge sort)— O(n log n); 需要 O(n) 额外存储空间

  二叉树排序(Binary tree sort) — O(nlogn); 需要 O(n) 额外存储空间

  计数排序  (counting sort) — O(n+k); 需要 O(n+k) 额外存储空间,k为序列中Max-Min+1

  桶排序 (bucket sort)— O(n); 需要 O(k) 额外存储空间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值