十大排序算法(Java实现)

零、简介

1. 排序与十大排序算法

排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
排序算法是《数据结构与算法》中最基本的算法之一。
八大排序算法指的是《数据结构与算法》中介绍的冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、基数排序,十大排序则是在此基础上加上计数排序和桶排序。

排序算法可以分为内部排序和外部排序:

  • 内部排序:所有排序操作都在内存中完成,不需要额外的磁盘或其他存储设备的辅助。这适用于数据量小到足以完全加载到内存中的情况。
  • 外部排序:当数据量过大,不可能全部加载到内存中时使用。外部排序通常涉及到数据的分区处理,部分数据被暂时存储在外部磁盘等存储设备上。

排序算法具有稳定和不稳定两种性质:

  • 稳定:如果 A 原本在 B 前面,而 A=B,排序之后 A 仍然在 B 的前面。
  • 不稳定:如果 A 原本在 B 的前面,而 A=B,排序之后 A 可能会出现在 B 的后面。

2. 排序算法类别

在这里插入图片描述

3.十大排序算法特征

排序算法时间复杂度(平均)时间复杂度(最差)时间复杂度(最好)空间复杂度排序方式稳定性
冒泡排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)内部排序稳定
选择排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2)$O(n^2) O ( 1 ) O(1) O(1)内部排序不稳定
插入排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)内部排序稳定
希尔排序 O ( n l o g n ) O(nlogn) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( n l o g n ) O(nlogn) O(nlogn) O ( 1 ) O(1) O(1)内部排序不稳定
归并排序 O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n ) O(n) O(n)外部排序稳定
快速排序 O ( n l o g n ) O(nlogn) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( n l o g n ) O(nlogn) O(nlogn) O ( l o g n ) O(logn) O(logn)内部排序不稳定
堆排序 O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( 1 ) O(1) O(1)内部排序不稳定
计数排序 O ( n + r ) O(n+r) O(n+r) O ( n + r ) O(n+r) O(n+r) O ( n + r ) O(n+r) O(n+r) O ( r ) O(r) O(r)外部排序稳定
桶排序 O ( n + k ) O(n+k) O(n+k) O ( n 2 ) O(n^2) O(n2) O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k)外部排序稳定
基数排序 O ( n ∗ k ) O(n*k) O(nk) O ( n ∗ k ) O(n*k) O(nk) O ( n ∗ k ) O(n*k) O(nk) O ( n + k ) O(n+k) O(n+k)外部排序稳定

其中,n表示数据规模,即待排序的数据规模;桶排序的k表示“桶” 的个数;计数排序的r表示数据范围;基数排序的d表示最大位数、r表示数据范围。

一、冒泡排序(BubbleSort)

1.算法简介

冒泡排序(Bubble Sort)是一种简单的排序算法,它会重复地比较相邻的两个元素,如果它们的顺序错误就交换它们。通过多次的比较和交换,最大(或最小)的元素会逐渐“浮”到数组的一端,向水下的鱼再向上冒泡一样,因此得名“冒泡”。

2.算法步骤

  • 1.比较相邻的元素,如果第一个比第二个大,就交换他们两个;
  • 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数;
  • 3.针对所有的元素重复以上的步骤,除了最后一个;
  • 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较;

3.算法特征

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  • 稳定性:稳定

4.算法实现

public class BubbleSortAlgorithm {

	public void bubbleSort(int[] arrays) {
		for (int i = 0; i < arrays.length; i++) {
			for (int j = 0; j+1 < arrays.length-i; j++) {
				if (arrays[j] > arrays[j+1]) {
					int temp = arrays[j+1];
					arrays[j+1] = arrays[j];
					arrays[j] = temp;
				}
			}
			System.out.println("第"+(i+1)+"趟之后:"+Arrays.toString(arrays));
		}
	}
	
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		new BubbleSortAlgorithm().bubbleSort(arrays);
		System.out.println("冒泡排序后:"+Arrays.toString(arrays));
	}
}

二、选择排序(SelectionSort)

1.算法简介

选择排序(Selection Sort)是一种简单直观的排序算法,它的基本思想是每次从待排序的数据中选择最小(或最大)的元素,放到已排序部分的末尾,直到所有元素都排序完成。

2.算法步骤

  • 1.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  • 2.再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
  • 3.重复第二步,直到所有元素均排序完毕。

3.算法特征

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  • 稳定性:不稳定

4.算法实现

public class SelectionSortAlgorithm {
	// 选择排序法
	public static void selectionSort(int arrays[]) {
        // 总共要经过 N-1 轮比较
        for (int i = 0; i < arrays.length-1; i++) {
            int min = i;
            // 每轮需要比较的次数 N-i
            for (int j = i + 1; j < arrays.length; j++) {
                if (arrays[j] < arrays[min]) {
                    // 记录目前能找到的最小值元素的下标
                    min = j;
                }
            }
            // 将找到的最小值和i位置所在的值进行交换
            if (i != min) {
                int temp = arrays[i];
                arrays[i] = arrays[min];
                arrays[min] = temp;
            }
        }
	}
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		selectionSort(arrays);
		System.out.println("选择排序后:"+Arrays.toString(arrays));
	}
}

三、插入排序(InsertionSort)

1.算法简介

插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作过程类似于整理扑克牌。插入排序的基本思想是将未排序的元素逐个插入到已排序的部分,构建一个有序序列。

2.算法步骤

  • 1.从第一个元素开始,该元素可以认为已经被排序
  • 2.取出下一个元素,在已经排序的元素序列中从后向前扫描(从第2个元素开始和前面已经排序好的比较)
  • 3.如果该元素(已排序)大于新元素,将该元素移到下一位置
  • 4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  • 5.将新元素插入到该位置后
  • 6.重复步骤2~5

3.算法特征

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  • 稳定性:稳定

4.算法实现

public class InsertionSortAlgorithm {	
	public void insertionSort(int arrays[]) {
		// 从第二个元素开始,和前面的有序表进行比较
		int j;
		for (int i = 1; i < arrays.length; i++) {
			int insertVal = arrays[i]; // 记录要插入的值,并保存在temp中,防止数据移动时该元素丢失
			for (j = i; j > 0 && arrays[j-1] > insertVal; j--) {
				arrays[j] = arrays[j-1];
			}
			arrays[j] = insertVal;
//			System.out.println("第"+i+"趟之后:"+Arrays.toString(arrays));
		}
	}
	
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		new InsertionSortAlgorithm().insertionSort(arrays);
		System.out.println("插入排序后:"+Arrays.toString(arrays));	
	}
}

四、希尔排序(ShellSort)

1.算法简介

希尔排序(Shell Sort)是一种改进的插入排序算法,也称为“缩小增量排序”。希尔排序通过引入一个增量序列来改进插入排序的性能,减少了数据移动的次数,从而提高了排序的效率。

2.算法步骤

  • 1.确定一个元素间隔数step。
  • 2.将参加排序的序列按此间隔数从第1个元素开始依次分成若干个子序列。
  • 3.在各个子序列中采用某种排序算法(例如插入排序算法)进行排序。
  • 4.减少间隔数,重复2-4步,直到间隔数step= 1。

3.算法特征

希尔排序的时间复杂度计算方式比较复杂。

  • 时间复杂度: O ( n ∗ l o g n ) O(n*logn) O(nlogn)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  • 稳定性:不稳定

4.算法实现

public class ShellSortAlgorithm {
	public void shellSort(int arrays[]) {
        int length = arrays.length;
        int temp;
        for (int step = length / 2; step >= 1; step /= 2) {
            for (int i = step; i < length; i++) {
                temp = arrays[i];
                int j = i - step;
                while (j >= 0 && arrays[j] > temp) {
                	arrays[j + step] = arrays[j];
                    j -= step;
                }
                arrays[j + step] = temp;
            }
        }
	}
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		new ShellSortAlgorithm().shellSort(arrays);
		System.out.println("归并排序后:"+Arrays.toString(arrays));	
	}
}

五、归并排序(MergeSort)

1.算法简介

归并排序(Merge Sort)是一种基于分治思想的经典排序算法,它将一个未排序的数组递归地分成两个子序列,对这两个子序列分别进行排序,然后将这两个有序子序列合并为一个有序序列。

2.算法步骤

  • 1.从第一个元素开始,该元素可以认为已经被排序
  • 2.取出下一个元素,在已经排序的元素序列中从后向前扫描(从第2个元素开始和前面已经排序好的比较)
  • 3.如果该元素(已排序)大于新元素,将该元素移到下一位置
  • 4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  • 5.将新元素插入到该位置后
  • 6.重复步骤2~5

3.算法特征

  • 时间复杂度: O ( n ∗ l o g n ) O(n*logn) O(nlogn)
  • 空间复杂度: O ( n ) O(n) O(n)
  • 稳定性:稳定

4.算法实现

public class MergeSortAlgorithm {
	public void mergeSort(int[] array) {
	    if(array == null || array.length <= 1) {
	        return;
	    }
	    int[] newArray = new int[array.length];
	    sort(array, 0, array.length-1, newArray);
	}
	// 排序
	public void sort(int arrays[], int left, int right, int[] newArray) {
	    if(left >= right) {
	        return;
	    }
        int mid = left + (right - left)/2;;
        sort(arrays, left, mid, newArray);
        sort(arrays, mid + 1, right, newArray);
        for(int i = left; i <= right; i++) {
            newArray[i] = arrays[i];
        }

    	// 归并
        int i = left;
        int j = mid + 1;
        int k = left;
        while(i <= mid && j <= right) {
            if(newArray[i] <= newArray[j]) { // 等号会影响算法的稳定性
                arrays[k++] = newArray[i++];
            } else {
                arrays[k++] = newArray[j++];
            }
        }
        if(i <= mid) {
            arrays[k++] = newArray[i++];
        }
	}

	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		new MergeSortAlgorithm().mergeSort(arrays);
		System.out.println("归并排序后:"+Arrays.toString(arrays));	
	}
}

六、快速排序(QuickSort)

1.算法简介

快速排序(Quick Sort)是一种常用的基于分治思想的排序算法,其核心思想是选择一个基准值,将数组分割为两部分,一部分的元素都小于基准值,另一部分的元素都大于基准值,然后对这两部分分别进行递归排序。

2.算法步骤

  • 1.从数列中挑出一个元素,称为“基准”
  • 2.重新排序数列,所有比基准值小的元素摆在基准的前面,所有比基准大的元素摆在基准的后面。
  • 3.递归地把小于基准值元素的子数列和大于基准值元素的子数列排序

3.算法特征

  • 时间复杂度: O ( n ∗ l o g n ) O(n*logn) O(nlogn)
  • 空间复杂度: O ( l o g n ) O(logn) O(logn)
  • 稳定性:不稳定

4.算法实现

public class QuickSortAlgorithm {
	//快速排序法
	public void quickSort(int arrays[], int left, int right) {
	    if (right < left) { //元素个数小于一个
	        return;
	    }
	    int pivotKey  = arrays[left];
	    int l = left; //左边界
	    int r = right; //右边界
	    while (l < r) {
	    	//右边的值大于基数时,右指针左移1位。即找出右边小于基数的值
	    	while (l < r && arrays[r] >= pivotKey) {
	    		r--;
	    	}	    	
	    	if (l < r) {
				arrays[l] = arrays[r]; //将右指针对应小于基数的值放到左指针所指的位置
				l++; //左指针被赋值为右边小于基数的值后,自增
			}	
	    	
	    	//左边的值小于基数时,左指针右移1位。即找出左边大于基数的值
	    	while (l < r && arrays[l] <= pivotKey) {
	    		l++;
	    	}
	    	if (l < r) { //相反,找到大于基数的下标
				arrays[r] = arrays[l];
				r--;
			}
		}
	    arrays[l] = pivotKey;
	    //处理当前数组的左半部分,不包括下标为pivot的元素
	    quickSort(arrays, left, r-1);
	    //处理当前数组的右半部分,不包括下标为pivot的元素
	    quickSort(arrays, l+1, right);	    
	}
	
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		new QuickSortAlgorithm().quickSort(arrays, 0, arrays.length-1);
		System.out.println("快速排序后:"+Arrays.toString(arrays));
	}
}

七、堆排序(HeapSort)

1.算法简介

堆排序(Heap Sort)是一种基于堆数据结构实现的排序算法,它利用最大堆(Max Heap)或最小堆(Min Heap)来实现排序过程。

堆是一种完全二叉树,其中每个父节点的值大于等于(最大堆)或小于等于(最小堆)其子节点的值。堆排序的基本思想是通过构建一个二叉堆,然后依次将堆顶元素(最大值或最小值)与堆底元素交换,调整堆使得剩余元素继续保持堆的性质,重复这个过程直到所有元素有序。

2.算法步骤

  • 1.构建一个堆Heap[0, … , … ,n-1];
  • 2.把堆首(最大值)和堆尾互换;
  • 3.把堆的尺寸缩小1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
  • 4.重复步骤 2,直到堆的尺寸为 1。

3.算法特征

  • 时间复杂度: O ( n ∗ l o g n ) O(n*logn) O(nlogn)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  • 稳定性:不稳定

4.算法实现

public class HeapSortAlgorithm {

    /**
     * 堆排序的主要入口方法,共两步。
     */
    public void heapSort(int[] arrays) {
        /*
         *  第一步:将数组堆化
         *  beginIndex = 第一个非叶子节点。
         *  从第一个非叶子节点开始即可。无需从最后一个叶子节点开始。
         *  叶子节点可以看作已符合堆要求的节点,根节点就是它自己且自己以下值为最大。
         */
        int len = arrays.length - 1;
        int beginIndex = (arrays.length >> 1)- 1;
        for (int i = beginIndex; i >= 0; i--) {
            maxHeapify(i, len, arrays);
        }
        /*
         * 第二步:对堆化数据排序
         * 每次都是移出最顶层的根节点A[0],与最尾部节点位置调换,同时遍历长度 - 1。
         * 然后从新整理被换到根节点的末尾元素,使其符合堆的特性。
         * 直至未排序的堆长度为 0。
         */
        for (int i = len; i > 0; i--) {
            swap(0, i, arrays);
            maxHeapify(0, i - 1, arrays);
        }
    }

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

    /**
         * 调整索引为 index 处的数据,使其符合堆的特性。
     *
     * @param index 需要堆化处理的数据的索引
     * @param len 未排序的堆(数组)的长度
     */
    private void maxHeapify(int index, int len, int[] arrays) {
        int li = (index << 1) + 1; // 左子节点索引
        int ri = li + 1;           // 右子节点索引
        int cMax = li;             // 子节点值最大索引,默认左子节点。
        if (li > len) return;      // 左子节点索引超出计算范围,直接返回。
        if (ri <= len && arrays[ri] > arrays[li]) // 先判断左右子节点,哪个较大。
            cMax = ri;
        if (arrays[cMax] > arrays[index]) {
            swap(cMax, index, arrays);      // 如果父节点被子节点调换,
            maxHeapify(cMax, len, arrays);  // 则需要继续判断换下后的父节点是否符合堆的特性。
        }
    }

    public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		new HeapSortAlgorithm().heapSort(arrays);
        System.out.println("  堆排序后:"+Arrays.toString(arrays));
    }
}

八、基数排序(Radix Sort)

1.算法简介

基数排序(Radix Sort)是一种非比较性的排序算法,它通过对整数按照位数进行分配和收集来实现排序。基数排序将整数视为d位数字序列,从低位到高位依次进行排序,最终得到有序的整数序列。

2.算法步骤

  • 1.将整数按位数切割成不同的数字
  • 2.然后按每个位数分别比较。

3.算法特征

基数排序的时间复杂度取决于待排序数据的最大位数d、数据范围r和数据个数n

  • 时间复杂度: O ( d + ( n + r ) ) O(d+(n+r)) O(d+(n+r))
  • 空间复杂度: O ( n + r ) O(n+r) O(n+r)
  • 稳定性:稳定

4.算法实现

public class RadixSortAlgorithm {
	//基数排序法
	public static void radixSort(int arrays[]) {
        int maxValue = Arrays.stream(arrays).max().getAsInt(); // 找出数组arrays中的最大值
        int exp = 1; // 指数
        int[] buf = new int[arrays.length]; // 存储"被排序数据"的临时数组
        // 从个位开始,对数组a按"指数"进行排序
        while (maxValue >= exp) {
            int[] buckets = new int[10]; // 将数字出现的次数存储在buckets[]中
            for (int i = 0; i < arrays.length; i++) {
                int digit = (arrays[i] / exp) % 10;
                buckets[digit]++;
            }
            for (int i = 1; i < 10; i++) {
            	buckets[i] += buckets[i - 1];
            }
            for (int i = arrays.length - 1; i >= 0; i--) {
                int digit = (arrays[i] / exp) % 10;
                buf[buckets[digit] - 1] = arrays[i];
                buckets[digit]--;
            }
            // 将排序好的数据赋值给a[]
            for (int i = 0; i < arrays.length; i++) {
            	arrays[i] = buf[i];
            }
            exp *= 10;
        }
	}
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		radixSort(arrays);
		System.out.println("基数排序后:"+Arrays.toString(arrays));
	}
}

九、计数排序(CountingSort)

1.算法简介

计数排序(Counting Sort)是一种非比较性的稳定排序算法,适用于对一定范围内的整数进行排序。计数排序的核心思想是统计每个元素出现的次数,然后根据元素的大小顺序输出排序后的结果。

计数排序存在两大局限性:

  • 数组中最大和最小的元素差距不能过大,因为会占用大量空间;
  • 当数组中的元素必须是非负整数,否则无法申请计数数组。

2.算法步骤

  1. 找出待排序的数组中最大和最小的元素,根据最大和最小元素的差值范围,申请额外计数数组。
  2. 统计数组中每个元素的出现次数,并将统计结果存储在额外的计数数组中。
  3. 根据计数数组中的值(即每个元素出现的次数),将对应的元素按顺序放入新的数组中,使得新数组中的元素有序。

3.算法特征

计数排序的时间复杂度取决于数据范围r(最大值与最小值之差加一)和数据个数n

  • 时间复杂度: O ( n + r ) O(n+r) O(n+r)
  • 空间复杂度: O ( r ) O(r) O(r)
  • 稳定性:稳定

4.算法实现

public class CountingSortAlgorithm {
	public void countingSort(int[] arrays, int maxValue) {
        int bucketLen = maxValue + 1;
        int[] bucket = new int[bucketLen];
        for (int value : arrays) {
            bucket[value]++;
        }
        int sortedIndex = 0;
        for (int j = 0; j < bucketLen; j++) {
            while (bucket[j] > 0) {
            	arrays[sortedIndex++] = j;
                bucket[j]--;
            }
        }
    }
	
    private int getMaxValue(int[] arrays) {
        int maxValue = arrays[0];
        for (int value : arrays) {
            if (maxValue < value) {
                maxValue = value;
            }
        }
        return maxValue;
    }
	
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		int maxValue = new CountingSortAlgorithm().getMaxValue(arrays);
		new CountingSortAlgorithm().countingSort(arrays, maxValue);
		System.out.println("计数排序后:"+Arrays.toString(arrays));
	}
}

十、桶排序(BucketSort)

1.算法简介

桶排序(Bucket Sort)又称箱排序,是计数排序的升级版。其算法原理是将元素分到有限数量的桶里,对每个桶中的元素进行排序,然后按顺序将各个桶的元素合并,得到最终有序的结果。
它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。是一种用空间换取时间的排序。
为了使桶排序更高效,应注意以下两点:

  • 在额外空间充足的情况下,尽量增大桶的数量
  • 使用的映射函数能够将输入的 n 个数据均匀的分配到 k 个桶中

2.算法步骤

  1. 寻找数组中最大元素和最小元素并计算桶的大小bucketSize和个数bucketCount;
  2. 将元素均匀地分散到多个桶中;
  3. 对每个桶中的元素进行排序(通常使用的是插入排序等简单排序算法);
  4. 合并各个桶中的元素,得到有序序列。

3.算法特征

桶排序的时间复杂度取决于桶的个数k和数据规模n

  • 时间复杂度: O ( n + k ) O(n+k) O(n+k)
  • 空间复杂度: O ( n + k ) O(n+k) O(n+k)
  • 稳定性:稳定

4.算法实现

public class BucketSortAlgorithm {
	public void bucketSort(int[] arrays) {
        if (arrays.length == 0) {
            return;
        }
        // 寻找最大和最小元素
        int minValue = arrays[0];
        int maxValue = arrays[0];
        for (int value : arrays) {
            if (value < minValue) {
                minValue = value;
            } else if (value > maxValue) {
                maxValue = value;
            }
        }
        int bucketSize = (maxValue - minValue) / arrays.length + 1; // 计数桶存储数的范围大小
        int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1; // 计数桶的个数,
        int[][] buckets = new int[bucketCount][0];

        // 利用映射函数将数据分配到各个桶中
        for (int i = 0; i < arrays.length; i++) {
            int index = (int) Math.floor((arrays[i] - minValue) / bucketSize);
            buckets[index] = arraysAppend(buckets[index], arrays[i]);
        }

        int arraysIndex = 0;
        for (int[] bucket : buckets) {
            if (bucket.length <= 0) {
                continue;
            }
            // 对每个桶进行排序,这里使用了库函数的快速排序
            Arrays.sort(bucket);
            for (int value : bucket) {
                arrays[arraysIndex++] = value;
            }
        }
	}
	
	// 自动扩容
    private int[] arraysAppend(int[] arr, int value) {
        arr = Arrays.copyOf(arr, arr.length + 1);
        arr[arr.length - 1] = value;
        return arr;
    }
    
	public static void main(String[] args) {
		int arrays[] = {6,2,13,27,49,74,12,64,5,4,-62,99,5,17,18,23,34,15,35,25,53,51};
		System.out.println("原始数据集:"+Arrays.toString(arrays));
		new BucketSortAlgorithm().bucketSort(arrays);
		System.out.println("   桶排序后:"+Arrays.toString(arrays));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

helloWorldZMY

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

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

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

打赏作者

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

抵扣说明:

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

余额充值