总览:
不断选择最值将其放在最终的位置上
数据移动最少,运行时间与数据输入时的顺序无关
数据量少
private static void sort(int[] nums){
int n=nums.length;
int minIndex,temp;
for(int i=0;i<n-1;i++){
minIndex=i;
for(int j=i+1;j<n;j++){
if(nums[j]<nums[minIndex]){
minIndex=j;
}
}
temp=nums[i];
nums[i]=nums[minIndex];
nums[minIndex]=temp;
}
}
像抓牌一样,将牌暂时放入现在的适当的位置。当到最后一个元素时就排序完成了
运行时间与输入情况有关,对于一个部分有序(数组中元素离最终位置都不远,或者一个有序的大数组加一个小数组)来说速度比较快
待排序数组基本有序
private static void sort(int[] nums) {
int n=nums.length;
int preIndex,current;
for(int i=1;i<n;i++){
preIndex=i-1;
current=nums[i];
while (preIndex>=0&&nums[preIndex]>current){
nums[preIndex+1]=nums[preIndex];
preIndex--;
}
nums[preIndex+1]=current;
}
}
十分简单,重复访问,依次比较进行交换
思路简单
无
private static void sort(int[] nums) {
int n=nums.length;
for(int i=0;i<n-1;i++){
for(int j=0;j<n-i-1;j++){
if(nums[j]>nums[j+1]){
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
}
}
}
使数组中任意间隔为h的元素是有序的。最后对于一个以1结尾的的h序列我们都能够将其排序。
基于插入排序的快速排序
大型数组,大多数情况下希尔排序都是比较高效且简单的算法
private static void sort(int[] nums) {
int n=nums.length;
int gap=n/2;
while (gap>0){
for(int j=gap;j<n;j++){
int i=j;
while ((i>=gap&&nums[i-gap]>nums[i])){
int temp=nums[i];
nums[i]=nums[i-gap];
nums[i-gap]=temp;
i-=gap;
}
}
gap=gap/2;
}
}
建立在归并操作上的一种算法,使用分治法的思想将小的有序的数组归并为一个大的数组
速度较快,不受输入数据的影响,所需额外空间与N成正比
private static void sort(int[] nums,int start,int end) {
if(start<end){
int mid=(start+end)/2;
sort(nums,start,mid);
sort(nums,mid+1,end);
merge(nums,start,mid,end);
}
}
private static void merge(int[] nums,int left,int mid,int right){
int []tmp=new int[nums.length];
int p1=left,p2=mid+1,k=left;
while (p1<=mid && p2<=right){
if(nums[p1]<=nums[p2])
tmp[k++]=nums[p1++];
else
tmp[k++]=nums[p2++];
}
while (p1<=mid)
tmp[k++]=nums[p1++];
while (p2<=right)
tmp[k++]=nums[p2++];
for (int i=left;i<=right;i++)
nums[i]=tmp[i];
}
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
应用广泛,原地排序,几乎不需要额外的空间
广泛
private static void sort(int[] nums,int start,int end) {
if(nums.length<0)
return;
if(start>=end)
return;
int left=start;
int right=end;
int temp=nums[left];
while (left<right){
while (left<right && nums[right]>=temp)
right--;
nums[left]=nums[right];
while (left<right && nums[left]<=temp)
left++;
nums[right]=nums[left];
}
nums[left]=temp;
sort(nums,start,left-1);
sort(nums,left+1,end);
}
利用堆这种数据结构,堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
public static void sort(int[] list) {
//构造初始堆,从第一个非叶子节点开始调整,左右孩子节点中较大的交换到父节点中
for (int i = (list.length) / 2 - 1; i >= 0; i--) {
headAdjust(list, list.length, i);
}
//排序,将最大的节点放在堆尾,然后从根节点重新调整
for (int i = list.length - 1; i >= 1; i--) {
int temp = list[0];
list[0] = list[i];
list[i] = temp;
headAdjust(list, i, 0);
}
}
private static void headAdjust(int[] list, int len, int i) {
int k = i, temp = list[i], index = 2 * k + 1;
while (index < len) {
if (index + 1 < len) {
if (list[index] < list[index + 1]) {
index = index + 1;
}
}
if (list[index] > temp) {
list[k] = list[index];
k = index;
index = 2 * k + 1;
} else {
break;
}
}
list[k] = temp;
}
计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
其排序速度快于任何比较排序算法。当k不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。
public static void sortCount(int[] arr, int min, int max) {
int len = arr.length;
int[] tem = new int[max - min + 1];
for(int i = 0; i < len; i++) {
tem[arr[i] - min] += 1;
}
for(int i = 0, index = 0; i < tem.length; i++) {
int item = tem[i];
while(item-- != 0) {
arr[index++] = i + min;
}
}
}
桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。
public static void main(String[] args) {
// 输入元素均在 [0, 10) 这个区间内
float[] arr = new float[] { 0.12f, 2.6f, 8.8f, 7.6f, 7.2f, 6.3f, 9.0f, 1.6f, 5.6f, 2.4f };
bucketSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void bucketSort(float[] arr) {
// 新建一个桶的集合
ArrayList<LinkedList<Float>> buckets = new ArrayList<LinkedList<Float>>();
for (int i = 0; i < 10; i++) {
// 新建一个桶,并将其添加到桶的集合中去。
// 由于桶内元素会频繁的插入,所以选择 LinkedList 作为桶的数据结构
buckets.add(new LinkedList<Float>());
}
// 将输入数据全部放入桶中并完成排序
for (float data : arr) {
int index = getBucketIndex(data);
insertSort(buckets.get(index), data);
}
// 将桶中元素全部取出来并放入 arr 中输出
int index = 0;
for (LinkedList<Float> bucket : buckets) {
for (Float data : bucket) {
arr[index++] = data;
}
}
}
/**
* 计算得到输入元素应该放到哪个桶内
*/
public static int getBucketIndex(float data) {
// 这里例子写的比较简单,仅使用浮点数的整数部分作为其桶的索引值
// 实际开发中需要根据场景具体设计
return (int) data;
}
/**
* 我们选择插入排序作为桶内元素排序的方法 每当有一个新元素到来时,我们都调用该方法将其插入到恰当的位置
*/
public static void insertSort(List<Float> bucket, float data) {
ListIterator<Float> it = bucket.listIterator();
boolean insertFlag = true;
while (it.hasNext()) {
if (data <= it.next()) {
it.previous(); // 把迭代器的位置偏移回上一个位置
it.add(data); // 把数据插入到迭代器的当前位置
insertFlag = false;
break;
}
}
if (insertFlag) {
bucket.add(data); // 否则把数据插入到链表末端
}
}
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
public static void main(String[] args) {
int[] arr = new int[] { 5,789,2138,456,3,1,9,1,13,4984,3 };
radixSort(arr,10000);
System.out.println(Arrays.toString(arr));
}
private static void radixSort(int[] array,int d)
{
int n=1;//代表位数对应的数:1,10,100...
int k=0;//保存每一位排序后的结果用于下一位的排序输入
int length=array.length;
int[][] bucket=new int[10][length];//排序桶用于保存每次排序后的结果,这一位上排序结果相同的数字放在同一个桶里
int[] order=new int[length];//用于保存每个桶里有多少个数字
while(n<d)
{
for(int num:array) //将数组array里的每个数字放在相应的桶里
{
int digit=(num/n)%10;
bucket[digit][order[digit]]=num;
order[digit]++;
}
for(int i=0;i<length;i++)//将前一个循环生成的桶里的数据覆盖到原数组中用于保存这一位的排序结果
{
if(order[i]!=0)//这个桶里有数据,从上到下遍历这个桶并将数据保存到原数组中
{
for(int j=0;j<order[i];j++)
{
array[k]=bucket[i][j];
k++;
}
}
order[i]=0;//将桶里计数器置0,用于下一次位排序
}
n*=10;
k=0;//将k置0,用于下一轮保存位排序结果
}
}
代码思路倒是很简单,就是利用线程睡眠来进行排序,让线程睡眠、
没啥特点就是好玩
无
public static void sleepSort(int[] array) {
for (int i : array) {
new Thread(()->{
try {
Thread.sleep(i);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(i);
}).start();
}
}
public static void main(String[] args) {
int[] array = { 10, 30, 50, 60, 100, 40, 150, 200, 70 };
sleepSort(array);
}
就是让系统随机排序,然后验证是否有序
巨复杂
无
public static void randSortX(int [] array){
List<Integer> list=new ArrayList<>();
for (Integer integer : array) {
list.add(integer);
}
int pre=0;
int index=0;
while(true){
pre=0;
for (index = 1; index < list.size(); index++) {
if(list.get(index)>list.get(pre)){
pre++;
}else{
break;
}
}
if(pre+1==list.size()){
break;
}
Collections.shuffle(list);
}
System.out.println(list.toString());
}
public static void main(String[] args) {
int[] array = { 10, 30, 50, 60, 100, 40, 150, 200, 70 };
randSortX(array);
}