java实现10大排序算法
冒泡排序
/**
* 冒泡排序
* @param arr
*/
public static void bubbleSort(int[] arr){
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-i-1; j++) {
if (arr[j]>arr[j+1]){//顺序
//交换
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
选择排序
/**
* 选择排序
* @param arr
*/
public static void selectionSort(int[] arr) {
int index ;
for (int i = 0; i < arr.length-1; i++) {//遍历的次数
index = i;
for (int j = i+1; j < arr.length; j++) {
if (arr[index]>arr[j]){
index=j;//找小的,把小的角标给index
}
}
//最后进行交换到第i个
int temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
}
插入排序
/**
* 插入排序:类似于打扑克整理牌时(从小到大排序,通过与前者一一比较确定其位置,)
* 也可以类比成麻将(一万到九万乱序,从左开始与其前者进行比较,比前者小,前者就往右移空出位置。。。
*
* @param arr
*/
public static void insertSort(int[] arr){
for (int i = 1; i < arr.length; i++) {//次数
int j = i-1;
int target = arr[i];//当前拿着的数据
while (j > -1 && target<arr[j]){
//往右移!能符合条件:
arr[j+1] = arr[j];
j--;
}
arr[j+1] = target;//将拿着的元素插进去
}
}
快速排序
/**
* 快速排序,找一个基准,左右两个指针,左指针往右走,走到大于基准的地方停下来
* 右指针往左走,走到小于基准的地方停下来,然后这两个数交换,
* 重复上述动作,直到左右指针拥抱
* (左指针会走到大与基准的地方停下,所以基准要和左指针-1的地方交换)
* 基准:(可以使用三元取中)
* @param arr
* @param small
* @param big
*/
public static void QUICKSORT(int[] arr, int small, int big){
if (small > big) {//终止条件
return;
}
int compare = arr[small];//基准值,用来比较
int p = small;//基准指针
int left = small+1;//最左边
int right = big;//最右边
while (left <= right){
while (left <= right && arr[left]<=compare){//找(大的数)位置停
left++;
}
while (left <= right && arr[right]>compare){//找(小的数)位置停
right--;
}
//都停下来之后进行交换
if (left < right) {//最后一次不用交换
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
//final
//把标准p换到 right 的位置,进行一波交换 【p,A,B,C,right{<compare},left{>compare},D,E,F】
int temp = arr[p];
arr[p] = arr[right];
arr[right] = temp;
//递归调用===从bigger分开;
QUICKSORT(arr,small,right-1);
QUICKSORT(arr,right+1,big);
}
希尔排序
/**
* 把数组按照间隔i挖出几组数比如【1,5,9,13】【2,6,10,14】【3,7,11,15】......i = 4
* 组内进行比较排序
* 再以(i/2)的间隔挖出几组数比如【1,3,5,7】【2,4,6,8】......i = 2
* 以此类推直至 i = 1 进行最后的排序
* @param arr
*/
public static void shellSort(int[] arr){
for (int i = arr.length/2; i > 0; i/=2) { //间隔i,每次减半
for (int j = i; j < arr.length; j++) {
int x = arr[j]; // x为将要插入的元素
int in = j-i; //前面已经排好序元素最后一个
while(in > -1 && arr[in]>x){//元素依次往后移,留出合适位置
arr[in+i]=arr[in];//类似于插入排序
in -= i;
}
arr[in+i]=x;
}
}
}
/**
* 归并排序
* @param arr
*/
public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
process(arr, 0, arr.length - 1);
}
//该方法表示将arr数组的L到R位置上的数字变为有序的
public static void process(int[] arr, int L, int R) {
//俗称base case,即划分到什么程度时,就不需要再继续划分了
if (L == R) {
return;
}
//求中间位置,L到mid是左侧递归部分的数据,mid+1到R是右侧递归部分的数据
int mid = L + ((R - L) >> 1);
//左右两侧进行递归拆分
process(arr, L, mid);
process(arr, mid + 1, R);
//再将arr中的左右两部分合并为有序的,L到mid为左侧部分,mid+1到R是右侧
//递归部分的数据,所以位置信息传三个参数就行,不用传mid+1参数
merge(arr, L, mid, R);
}
//
public static void merge(int[] arr, int L, int M, int R) {
//准备辅助数组,存放排序后的数据
int[] help = new int[R - L + 1];
int i = 0;
//左侧数据起始位置
int p1 = L;
//右侧数据起始位置
int p2 = M + 1;
//左右两侧都没遍历完,即p1、p2都没越界
while (p1 <= M && p2 <= R) {
//将左右部分的数据进行比较,小的数据存放到辅助数组,
//然后help和添加到辅助数组的部分指针(p1或p2)进行右移
help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
//当跳出wile循环,代表左或右某个部分已经遍历完了,然后将未
//遍历完的追加到辅助数组尾部,下面的两个while循环只能有一个执行
while (p1 <= M) {
help[i++] = arr[p1++];
}
while (p2 <= R) {
help[i++] = arr[p2++];
}
//将辅助数组中的数据追加到原arr数组中
for (i = 0; i < help.length; i++) {
arr[L + i] = help[i];
}
}
/**
* 计数排序
* @param a
*/
static void CountSort(int[] a) {
int max = a[0];
int min = a[0];
for (int e : a) {
if (e > max) {
max = e;
}
}
for (int e : a) {
if (e < min) {
min = e;
}
}
int[] helper = new int[max - min + 1];
for (int e : a) {
helper[e-min]++;//减去最小值。
}
int current = 0;//数据回填的位置[指针]
for (int i = 0; i < helper.length; i++) {
while (helper[i] > 0) {
a[current++] = i+min;//(i为元素 还要加上最小值)
helper[i]--;
}
}
}
/**
* 堆排序
* @param sourceArray
* @return
* @throws Exception
*/
public int[] HeapSort(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
int len = arr.length;
buildMaxHeap(arr, len);
for (int i = len - 1; i > 0; i--) {
swap(arr, 0, i);
len--;
heapify(arr, 0, len);
}
return arr;
}
private void buildMaxHeap(int[] arr, int len) {
for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
heapify(arr, i, len);
}
}
private void heapify(int[] arr, int i, int len) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int largest = i;
if (left < len && arr[left] > arr[largest]) {
largest = left;
}
if (right < len && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
swap(arr, i, largest);
heapify(arr, largest, len);
}
}
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void bucketSort(int[] arr){
/*计算最大值与最小值*/
int max = 0;
int min = 0;
for(int i = 0; i < arr.length; i++){
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
/*计算桶的数量*/
int bucketNum = (max-min)/arr.length+1;
/*用ArrayList组织对应的桶*/
List<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
for(int i = 0;i<bucketNum;i++){
bucketArr.add(new ArrayList<Integer>());
}
/*将每个元素放入对应的桶*/
for(int i = 0; i<arr.length;i++){
/*找元素对应的桶*/
int num = (arr[i]-min)/(arr.length);
/*在同种放入对应的元素*/
bucketArr.get(num).add(arr[i]);
}
/*对每个桶内的元素进行排序*/
for(int i = 0; i<bucketArr.size();i++){
Collections.sort(bucketArr.get(i));
}
/*将桶中的元素赋值到原始数组arr*/
for(int i = 0,index = 0; i < bucketArr.size(); i++){
for(int j = 0; j < bucketArr.get(i).size(); j++){
arr[index++] = bucketArr.get(i).get(j);
}
}
}
/**
* 基数排序
* @param array
* @param digit
*/
static void radixSort(int[] array, int digit) {
/*此处桶数之所以取10,是因为数字0-9总共是十个数字,因此每趟比较时,分为10个桶*/
int radix = 10;
int i = 0, j = 0;
/*存放各个桶的数据统计个数*/
int[] count = new int[radix];
int[] bucket = new int[array.length];
/*按照从低位到高位的顺序执行排序过程*/
for (int d = 1; d <= digit; d++) {
/*置空各个桶的数据统计*/
for (i = 0; i < radix; i++) {
count[i] = 0;
}
/*统计各个桶将要装入的数据个数*/
for (i = 0; i <array.length; i++) {
j = getDigit(array[i], d);
count[j]++;
}
/*count[i]表示第i个桶的右边界索引*/
for (i = 1; i < radix; i++) {
count[i] = count[i] + count[i - 1];
}
/*将数据依次装入桶中,这里要从右向左扫描,保证排序稳定性*/
for (i = array.length-1; i >= 0; i--) {
j = getDigit(array[i], d);
/*求出元素的第k位的数字, 例如:576的第3位是5*/
bucket[count[j] - 1] = array[i];
/*放入对应的桶中,count[j]-1是第j个桶的右边界索引,对应桶的装入数据索引减一*/
count[j]--; //
}
/*将已分配好的桶中数据再倒出来,此时已是对应当前位数有序的表*/
for (i = 0, j = 0; i < array.length; i++, j++) {
array[i] = bucket[j];
}
}
}
/*获取x这个数的d位数上的数字,比如获取123的1位数,结果返回3*/
static int getDigit(int num, int d) {
/*本实例中的最大数是百位数,所以只要到100就可以了*/
int digit[] = {1, 10, 100};
return ((num/digit[d-1]) % 10);
}
//更新中。。。
如有错误欢迎指正