赞
踩
两两比较交换位置,最大的升到最后
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
当输入的数据已经是正序时(都已经是正序了,我还要你冒泡排序有何用啊)。
当输入的数据是反序时(写一个 for 循环反序输出数据不就行了,干嘛要用你冒泡排序呢,我是闲的吗)。
- public class BubbleSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝,不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- for (int i = 1; i < arr.length; i++) {
- // 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。
- boolean flag = true;
- for (int j = 0; j < arr.length - i; j++) {
- if (arr[j] > arr[j + 1]) {
- int tmp = arr[j];
- arr[j] = arr[j + 1];
- arr[j + 1] = tmp;
- flag = false;
- }
- }
- if (flag) {
- break;
- }
- }
- return arr;
- }
- }
依次选择最小插入新队列,原来元素被移除
选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。
- public class SelectionSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- // 总共要经过 N-1 轮比较
- for (int i = 0; i < arr.length - 1; i++) {
- int min = i;
- // 每轮需要比较的次数 N-i
- for (int j = i + 1; j < arr.length; j++) {
- if (arr[j] < arr[min]) {
- // 记录目前能找到的最小值元素的下标
- min = j;
- }
- }
- // 将找到的最小值和i位置所在的值进行交换
- if (i != min) {
- int tmp = arr[i];
- arr[i] = arr[min];
- arr[min] = tmp;
- }
- }
- return arr;
- }
- }
元素有序插入(比较获得位置)新队列
插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
插入排序和冒泡排序一样,也有一种优化算法,叫做拆半插入。
- public class InsertSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝,不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- // 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
- for (int i = 1; i < arr.length; i++) {
- // 记录要插入的数据
- int tmp = arr[i];
- // 从已经排序的序列最右边的开始比较,找到比其小的数
- int j = i;
- while (j > 0 && tmp < arr[j - 1]) {
- arr[j] = arr[j - 1];
- j--;
- }
- // 存在比其小的数,插入
- if (j != i) {
- arr[j] = tmp;
- }
- }
- return arr;
- }
- }
先子序列插入,再整个序列插入
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;
希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
- public static void shellSort(int[] arr) {
- int length = arr.length;
- int temp;
- for (int step = length / 2; step >= 1; step /= 2) {
- for (int i = step; i < length; i++) {
- temp = arr[i];
- int j = i - step;
- while (j >= 0 && arr[j] > temp) {
- arr[j + step] = arr[j];
- j -= step;
- }
- arr[j + step] = temp;
- }
- }
- }
归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:
自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第 2 种方法);
自下而上的迭代;
- public class MergeSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝,不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- if (arr.length < 2) {
- return arr;
- }
- int middle = (int) Math.floor(arr.length / 2);
- int[] left = Arrays.copyOfRange(arr, 0, middle);
- int[] right = Arrays.copyOfRange(arr, middle, arr.length);
- return merge(sort(left), sort(right));
- }
- protected int[] merge(int[] left, int[] right) {
- int[] result = new int[left.length + right.length];
- int i = 0;
- while (left.length > 0 && right.length > 0) {
- if (left[0] <= right[0]) {
- result[i++] = left[0];
- left = Arrays.copyOfRange(left, 1, left.length);
- } else {
- result[i++] = right[0];
- right = Arrays.copyOfRange(right, 1, right.length);
- }
- }
- while (left.length > 0) {
- result[i++] = left[0];
- left = Arrays.copyOfRange(left, 1, left.length);
- }
- while (right.length > 0) {
- result[i++] = right[0];
- right = Arrays.copyOfRange(right, 1, right.length);
- }
- return result;
- }
- }
基准值+冒泡
- public class QuickSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝,不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- return quickSort(arr, 0, arr.length - 1);
- }
- private int[] quickSort(int[] arr, int left, int right) {
- if (left < right) {
- int partitionIndex = partition(arr, left, right);
- quickSort(arr, left, partitionIndex - 1);
- quickSort(arr, partitionIndex + 1, right);
- }
- return arr;
- }
- private int partition(int[] arr, int left, int right) {
- // 设定基准值(pivot)
- int pivot = left;
- int index = pivot + 1;
- for (int i = index; i <= right; i++) {
- if (arr[i] < arr[pivot]) {
- swap(arr, i, index);
- index++;
- }
- }
- swap(arr, pivot, index - 1);
- return index - 1;
- }
- private void swap(int[] arr, int i, int j) {
- int temp = arr[i];
- arr[i] = arr[j];
- arr[j] = temp;
- }
- }
- public class HeapSort implements IArraySort {
- @Override
- public int[] sort(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 class CountingSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝,不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- int maxValue = getMaxValue(arr);
- return countingSort(arr, maxValue);
- }
- private int[] countingSort(int[] arr, int maxValue) {
- int bucketLen = maxValue + 1;
- int[] bucket = new int[bucketLen];
- for (int value : arr) {
- bucket[value]++;
- }
- int sortedIndex = 0;
- for (int j = 0; j < bucketLen; j++) {
- while (bucket[j] > 0) {
- arr[sortedIndex++] = j;
- bucket[j]--;
- }
- }
- return arr;
- }
- private int getMaxValue(int[] arr) {
- int maxValue = arr[0];
- for (int value : arr) {
- if (maxValue < value) {
- maxValue = value;
- }
- }
- return maxValue;
- }
- }
- public class BucketSort implements IArraySort {
- private static final InsertSort insertSort = new InsertSort();
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝,不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- return bucketSort(arr, 5);
- }
- private int[] bucketSort(int[] arr, int bucketSize) throws Exception {
- if (arr.length == 0) {
- return arr;
- }
- int minValue = arr[0];
- int maxValue = arr[0];
- for (int value : arr) {
- if (value < minValue) {
- minValue = value;
- } else if (value > maxValue) {
- maxValue = value;
- }
- }
- int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1;
- int[][] buckets = new int[bucketCount][0];
- // 利用映射函数将数据分配到各个桶中
- for (int i = 0; i < arr.length; i++) {
- int index = (int) Math.floor((arr[i] - minValue) / bucketSize);
- buckets[index] = arrAppend(buckets[index], arr[i]);
- }
- int arrIndex = 0;
- for (int[] bucket : buckets) {
- if (bucket.length <= 0) {
- continue;
- }
- // 对每个桶进行排序,这里使用了插入排序
- bucket = insertSort.sort(bucket);
- for (int value : bucket) {
- arr[arrIndex++] = value;
- }
- }
- return arr;
- }
- /**
- * 自动扩容,并保存数据
- */
- private int[] arrAppend(int[] arr, int value) {
- arr = Arrays.copyOf(arr, arr.length + 1);
- arr[arr.length - 1] = value;
- return arr;
- }
- }
- /**
- * 基数排序
- * 考虑负数的情况还可以参考: sorting - sort翻译 - 基数排序维基百科 - Solved
- */
- public class RadixSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝,不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- int maxDigit = getMaxDigit(arr);
- return radixSort(arr, maxDigit);
- }
- /**
- * 获取最高位数
- */
- private int getMaxDigit(int[] arr) {
- int maxValue = getMaxValue(arr);
- return getNumLenght(maxValue);
- }
- private int getMaxValue(int[] arr) {
- int maxValue = arr[0];
- for (int value : arr) {
- if (maxValue < value) {
- maxValue = value;
- }
- }
- return maxValue;
- }
- protected int getNumLenght(long num) {
- if (num == 0) {
- return 1;
- }
- int lenght = 0;
- for (long temp = num; temp != 0; temp /= 10) {
- lenght++;
- }
- return lenght;
- }
- private int[] radixSort(int[] arr, int maxDigit) {
- int mod = 10;
- int dev = 1;
- for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
- // 考虑负数的情况,这里扩展一倍队列数,其中 [0-9]对应负数,[10-19]对应正数 (bucket + 10)
- int[][] counter = new int[mod * 2][0];
- for (int j = 0; j < arr.length; j++) {
- int bucket = ((arr[j] % mod) / dev) + mod;
- counter[bucket] = arrayAppend(counter[bucket], arr[j]);
- }
- int pos = 0;
- for (int[] bucket : counter) {
- for (int value : bucket) {
- arr[pos++] = value;
- }
- }
- }
- return arr;
- }
- /**
- * 自动扩容,并保存数据
- */
- private int[] arrayAppend(int[] arr, int value) {
- arr = Arrays.copyOf(arr, arr.length + 1);
- arr[arr.length - 1] = value;
- return arr;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。