java的十大排序算法

1、冒泡排序(每一躺选出一个最大或者最小放在最后)

import java.util.Arrays;

/**
 * 
 * <p>Title: a1BubbleSort</p>  
 * <p>Description: 稳定的排序算法 </p>  
 * @author Shenxinyuan
 * @date 2020年9月11日
 */
public class a1BubbleSort {

	public static void main(String[] args) {
		// System.out.println("你好,java!");

		int[] arr = { 4, 8, 9, 5, 7, 0, -1 };
		BubbleSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	/**
	 * 
	 * <p>Title: BubbleSort</p>  
	 * <p>Description: 空间复杂度(O(1))   时间复杂度(O(n^2))</p>  
	 * @param arr
	 */
	public static void BubbleSort(int[] arr) {
		if (arr == null || arr.length == 0) {
			return;
		}
		//优化,置一个变量判断是否发生交换,每一趟都少遍历比较一个数
		boolean label = true;
		for (int i = 0; i < arr.length && label; i++) {
			label = false;
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j + 1] < arr[j]) {
					int temp = arr[j + 1];
					arr[j + 1] = arr[j];
					arr[j] = temp;
					label = true;
				}
			}
		}
	}
}

2、简单选择排序及其优化

思想:每一躺找出最大或者最小的元素的下标跟对应位置交换
优化思想:每一躺找出最大和最小的元素的下标跟对应位置交换

import java.util.Arrays;

public class a2SelectSort {
	public static void main(String[] args) {
		int[] arr = { 4, 8, 9, 5, 7, 0, -1 };
		//SelectSort(arr);
		optimizedSelectSort(arr);
		System.out.println(Arrays.toString(arr));
	}
		
	//不稳定的排序算法,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,
    // 那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法
	private static void SelectSort(int[] arr) {
		// TODO Auto-generated method stub
		if(arr==null || arr.length==0) {
			return;
		}
		//时间复杂度(O(n^2))   空间复杂度(O(1))
	    //从待排序列选择最大或最小数据跟第一个交换
		for(int i =0;i<arr.length;i++) {
			int minIndex = i;
			for(int j =i+1;j<arr.length;j++) {
				//升序
				if(arr[j]<arr[minIndex]) {
					minIndex = j;
				}
			}
			if(minIndex != i) {
				swap(i, minIndex, arr);
			}
		}
		
	}
	
	//从待排序列中选择最大值和最小值选择排列
    //时间复杂度(O(n/2))既O(N) 空间复杂度(O(1))
	private static void optimizedSelectSort(int[] arr) {
		if(arr == null|| arr.length == 0) {
			return;
		}
		
		for(int i=0;i<=(arr.length>>1);i++) {
			int minIndex = i;
			int maxIndex = i;
			for(int j =i+1;j<=arr.length-1-i;j++) {
				if(arr[j]<arr[minIndex]) {
					minIndex = j;
					continue;
				}
				if(arr[j]>arr[maxIndex]) {
					maxIndex = j;
				}
			}
			if(minIndex != i) {
				swap(i, minIndex, arr);
			}
			if(maxIndex != i) {
				swap(arr.length-1-i, maxIndex, arr);
			}
		}
	}

	private static void swap(int i, int j, int[] arr) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}

3、插入排序

思想:在有序序列中找第一个比无需序列中第一个元素大的元素的下标,然后将该下标的元素放到有序序列的对应元素的前边
优化思想:在有序列中找第一个比无序序列中第一个元素小的元素的下标,然后将该下标的元素放到有序序列对应元素的后边。

import java.util.Arrays;

public class a3InsertSort {
	public static void main(String[] args) {
		int[] arr = { 4, 8, 9, 5, 7, 0, -1 };
		//InsertSort(arr);
		optimizedInsertSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	private static void InsertSort(int[] arr) {
		// TODO Auto-generated method stub
		if(arr == null||arr.length==0) {
			return;
		}
		
		for(int i =0;i<arr.length;i++) {
			int j;
			//在前i个升序数据,找到比第i个数据大的数,跳出循环开始交换数据
			for(j =0;j<i;j++) {
				if(arr[j] > arr[i]) {
					break;
				}
			}
			
			//以交换的形式,挪动数据arr[i]到有序数据的第j位
			for(int k = i-1;k>= j;k--) {
				swap(k+1, k, arr);
			}
		}
	}
	
	private static void optimizedInsertSort(int[] arr) {
		// TODO Auto-generated method stub
		if(arr == null||arr.length==0) {
			return;
		}else {
			for(int i= 0;i<arr.length;i++) {
				int j;
				int temp = arr[i];//把第i个数据保存在temp中,方便交换数据
				//升序
				for(j = i-1;j>=0;j--) {
					//在前i个有序数据中招第一个比第i个小的数,交换
					if(arr[j] < temp) {
						break;
					}else {
						//移动数据ing
						arr[j+1] = arr[j];
					}
				}
				//找到该位置,把temp给arr[j+1]
				arr[j+1] = temp;
			}
		}
	}
	
	private static void swap(int i, int j, int[] arr) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}

4、希尔排序(优化插入排序的拓展)

import java.util.Arrays;

public class a3ShellSort {

	public static void main(String[] args) {
		int[] arr = {10, 8, 1, 0, 19,
                2, 4, 28, 30, 56,
                24, 9, 5, 15, 12,
                11, 44, 77};
        shellSortSort(arr, 3);
        //System.out.println(Arrays.toString(arr));
        for(int demo:arr) {
        	
        	System.out.print(demo+" ");
        }
	}

	private static void shellSortSort(int[] arr, int gap) {
		// TODO Auto-generated method stub
		while(gap >= 1) {//直到间距为1
			for(int i =0;i<arr.length;i++) {
				int j =0;
				int temp = arr[i];
				for(j = i-gap;j>=0;j-=gap) {
					if(arr[j] <= temp) {
						break;
					}else {
						arr[j+gap] = arr[j];
					}
				}
				arr[j+gap] = temp;
			}
			gap--;
		}
	
	}

	
}

5、快速选择排序

import java.util.Arrays;
import java.util.Stack;

public class a4QuickSort {
	public static void main(String[] args) {
		int[] arr = {10, 2, 19, 0, 8, 100, 28, 7, 1, 15,7};
		quickSort(arr);
		//quickSortByWhile(arr);
		System.out.println(Arrays.toString(arr));
	}

	private static void quickSort(int[] arr) {
		// TODO Auto-generated method stub
		if (arr.length == 0 || arr == null) {
            return ;
        } else {
            quick(arr,0,arr.length-1);
        }
	}

	private static void quick(int[] arr, int low, int high) {
		// TODO Auto-generated method stub
		
		int partition = partition(low,high,arr);
        //partition左边的数据都比它小,右边的数据都比他大
        //判断左边的数据大于1 个
        if(partition > low +1){
            quick(arr, low,partition-1);
        }
        //判断右边的数据大于1 个
        if(partition < high-1){
            quick(arr, partition+1,high);
        }
	}

	private static int partition(int low, int high, int[] arr) {
		// TODO Auto-generated method stub
		int mark = arr[low];
        while (low < high) {
            //从后往前找比基准数据小的元素
            while (arr[high] >= mark && low < high) {
                high--;     //high可能会越界
            }
            if (low == high) {
                break;
            }
            if(arr[high]<mark){
                arr[low] = arr[high];
            }
            //从后往前找比基准数据小的元素
            while (arr[low] <= mark && low < high) {
                low++;
            }
            if (low == high) {
                break;
            }
            if(arr[low]>mark) {
                arr[high] = arr[low];
            }
        }
        arr[low] = mark;
		return low;
	}

	private static void quickSortByWhile(int[] arr) {
		// TODO Auto-generated method stub
		//参数合法性判断
        if(arr == null||arr.length==0){
            return;
        }
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        stack.push(arr.length-1);
        while(!stack.isEmpty()){
            int high = stack.pop();
            int low = stack.pop();
            //mark左边的数字都比他小,右边的数值都比他大
            int mid = partition(low,high,arr);
            //保证partition后的徐磊长度大于一
            //判断左边序列的个数是否大于一
            if(mid > low+1){
                stack.push(low);
                stack.push(mid-1);
            }
            //判断右边序列的个数是否大于一
            if(mid < high-1){
                stack.push(mid+1);
                stack.push(high);
            }
        }
	}
}

6、堆排序

import java.util.Arrays;
//堆排序的时间复杂度为:O(nlogn)
//空间复杂度:因为堆排序是就地排序,空间复杂度为常数:O(1)
public class a5HeapSort {
	public static void main(String[] args) {
		int[] arr = {16, 7, 3, 20, 17, 8};
        heapSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
        System.out.println();
        System.out.println(Arrays.toString(arr));
	}

	private static void heapSort(int[] arr) {
		// TODO Auto-generated method stub
		//创建堆,大根
        for (int i = (arr.length - 1) / 2; i >= 0; i--) {
            //从第一个非叶子结点从下至上,从右至左调整结构
            adjustHeap(arr, i, arr.length);
        }
        //调整堆结构+交换堆顶元素与末尾元素
        for (int i = arr.length - 1; i > 0; i--) {
            //将堆顶元素与末尾元素进行交换
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            //重新对堆进行调整
            adjustHeap(arr, 0, i);
        }
	}

	private static void adjustHeap(int[] arr, int parent, int length) {
		// TODO Auto-generated method stub
		//将temp作为父节点
        int temp = arr[parent];
        //左孩子
        int lChild = 2 * parent + 1;
        while (lChild < length) {
            //右孩子
            int rChild = lChild + 1;
            // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
            if (rChild < length && arr[lChild] < arr[rChild]) {
                lChild++;
            }
            // 如果父结点的值已经大于孩子结点的值,则直接结束
            if (temp >= arr[lChild]) {
                break;
            }
            // 把孩子结点的值赋给父结点
            arr[parent] = arr[lChild];
            //选取孩子结点的左孩子结点,继续向下筛选
            parent = lChild;
            lChild = 2 * lChild + 1;
        }
        arr[parent] = temp;
	}
}

7、归并排序


public class a6MergeSort {

	public static void main(String[] args) {
		int[] a = {49, 38, 65, 97, 76, 13, 27, 50};
        mergeSort(a, 0, a.length - 1);
        System.out.println("排好序的数组:");
        for (int e : a)
            System.out.print(e + " ");
	}

	private static void mergeSort(int[] a, int start, int end) {
		// TODO Auto-generated method stub
		if (start < end) {//当子序列中只有一个元素时结束递归
            int mid = (start + end) / 2;//划分子序列
            mergeSort(a, start, mid);//对左侧子序列进行递归排序
            mergeSort(a, mid + 1, end);//对右侧子序列进行递归排序
            merge(a, start, mid, end);//合并
        }
	}

	//空间复杂度度较大O(n)
	//时间复杂度:nlog2n
	private static void merge(int[] a, int left, int mid, int right) {
		// TODO Auto-generated method stub
		int[] tmp = new int[a.length];//辅助数组
        int p1 = left, p2 = mid + 1, k = left;//p1、p2是检测指针,k是存放指针

        while (p1 <= mid && p2 <= right) {
            if (a[p1] <= a[p2])
                tmp[k++] = a[p1++];
            else
                tmp[k++] = a[p2++];
        }

        //把剩余元素放入temp临时数组
        while (p1 <= mid) tmp[k++] = a[p1++];//如果第一个序列未检测完,直接将后面所有元素加到合并的序列中
        while (p2 <= right) tmp[k++] = a[p2++];//同上

        //复制回原素组
        for (int i = left; i <= right; i++)
            a[i] = tmp[i];
	}
}

8、计数排序

非比较类型的排序

/**
     * 计数排序
     *
     * @param array
     * @return
     */
    public static int[] CountingSort(int[] array) {
        if (array.length == 0) return array;
        int bias, min = array[0], max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] > max)
                max = array[i];
            if (array[i] < min)
                min = array[i];
        }
        bias = 0 - min;
        int[] bucket = new int[max - min + 1];
        Arrays.fill(bucket, 0);
        for (int i = 0; i < array.length; i++) {
            bucket[array[i] + bias]++;
        }
        int index = 0, i = 0;
        while (index < array.length) {
            if (bucket[i] != 0) {
                array[index] = i - bias;
                bucket[i]--;
                index++;
            } else
                i++;
        }
        return array;
    }

9、桶排序

放倒的桶排序,或者“放倒的hashmap”
桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。

/**
     * 桶排序
     * 
     * @param array
     * @param bucketSize
     * @return
     */
    public static ArrayList<Integer> BucketSort(ArrayList<Integer> array, int bucketSize) {
        if (array == null || array.size() < 2)
            return array;
        int max = array.get(0), min = array.get(0);
        // 找到最大值最小值
        for (int i = 0; i < array.size(); i++) {
            if (array.get(i) > max)
                max = array.get(i);
            if (array.get(i) < min)
                min = array.get(i);
        }
        int bucketCount = (max - min) / bucketSize + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount);
        ArrayList<Integer> resultArr = new ArrayList<>();
        for (int i = 0; i < bucketCount; i++) {
            bucketArr.add(new ArrayList<Integer>());
        }
        for (int i = 0; i < array.size(); i++) {
            bucketArr.get((array.get(i) - min) / bucketSize).add(array.get(i));
        }
        for (int i = 0; i < bucketCount; i++) {
            if (bucketSize == 1) { // 如果带排序数组中有重复数字时  感谢 @见风任然是风 朋友指出错误
                for (int j = 0; j < bucketArr.get(i).size(); j++)
                    resultArr.add(bucketArr.get(i).get(j));
            } else {
                if (bucketCount == 1)
                    bucketSize--;
                ArrayList<Integer> temp = BucketSort(bucketArr.get(i), bucketSize);
                for (int j = 0; j < temp.size(); j++)
                    resultArr.add(temp.get(j));
            }
        }
        return resultArr;
    }

10、基数排序

有一点点类似于hashmap的数据结构
基数排序基于分别排序,分别收集,所以是稳定的。

/**
     * 基数排序
     * @param array
     * @return
     */
    public static int[] RadixSort(int[] array) {
        if (array == null || array.length < 2)
            return array;
        // 1.先算出最大数的位数;
        int max = array[0];
        for (int i = 1; i < array.length; i++) {
            max = Math.max(max, array[i]);
        }
        int maxDigit = 0;
        while (max != 0) {
            max /= 10;
            maxDigit++;
        }
        int mod = 10, div = 1;
        ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
        for (int i = 0; i < 10; i++)
            bucketList.add(new ArrayList<Integer>());
        for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
            for (int j = 0; j < array.length; j++) {
                int num = (array[j] % mod) / div;
                bucketList.get(num).add(array[j]);
            }
            int index = 0;
            for (int j = 0; j < bucketList.size(); j++) {
                for (int k = 0; k < bucketList.get(j).size(); k++)
                    array[index++] = bucketList.get(j).get(k);
                bucketList.get(j).clear();
            }
        }
        return array;
    }

部分参考自https://www.cnblogs.com/xikui/p/11196148.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值