/**
* 冒泡排序(Bubble Sort)
* 进行两层循环嵌套,内层循环每进行一次会将最大的数交换数组末尾,外层循环控制控制内层循环执行次数和循环的结束位置(因为每执行一次本次循环的最大数已经放在了最后)
*/
public static void BubbleSort(int[] a) {
int bank;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length - i - 1; j++) {
if (a[j] > a[j + 1]) {
bank = a[j];
a[j] = a[j + 1];
a[j + 1] = bank;
}
}
}
}
/**
* 选择排序(Selection Sort)
* 进行两层循环嵌套,外层循环从角标0开始遍历传入内层循环,内层循环从传入角标之后开始遍历,记录内层最小值的角标,最后将外层角标和最小值角标数据交换,然后重复外层循环直至外层循环遍历完成
* 选择排序非常类似冒泡排序,但是相较冒泡排序效率更高,因为冒泡排序是多次交换位置才能完成一个数字的排序,但是选在排序通过记录位置的原理只在最后进行一次交换,所以效率更高
*/
public static void SelectionSort(int[] a) {
int bank;
for (int i = 0; i < a.length; i++) {
int marker = i;
for (int j = i + 1; j < a.length; j++) {
if (a[marker] > a[j]) {
marker = j;
}
}
bank = a[i];
a[i] = a[marker];
a[marker] = bank;
}
}
/**
* 插入排序(Insertion Sort)
* for循环嵌套while,外层循环取值传入while,while记录传入值应该所在的位置然后进行交换,外层循环继续循环交换后的位置直到此位置不需要交换
*/
public static void InsertionSort(int[] a) {
int bank;
for (int i = 1; i < a.length; i++) {
int marker = i;
while (marker > 0 && a[i] < a[marker - 1]) {
marker = marker - 1;
}
if (marker != i) {
bank = a[i];
a[i] = a[marker];
a[marker] = bank;
i--;
}
}
}
/**
* 希尔排序(Shell Sort)
* 双层循环嵌套,外层循环创建交换间隔,内层循环根据间隔进行判断并将较大的数交换到后侧(间隔50,进行交换的数据0-50,while循环会在本组内不断向前交换较小值,
* 每次内层循环执行完成会将所在间隔组排序完毕(0-50-100-150),外层循环缩小间隔每次二分之一在最后间隔会成为1,此时和插入排序逻辑相同可以保证所有数据排序完毕
* 希尔排序相较插入排序效率会高非常多,比如队列末尾的数组如果最小那么希尔排序只需要交换一次,而插入排序需要交换次数为队列长度减一
*/
public static void ShellSort(int[] a) {
int bank;
for (int deviation = a.length / 2; deviation > 0; deviation = deviation / 2) {
for (int i = deviation; i < a.length; i++) {
int j = i;
int marker;
bank = a[i];
while ((marker = j - deviation) >= 0 && bank < a[marker]) {
a[j] = a[marker];
a[marker] = bank;
j = marker;
}
}
}
}
/**
* 归并排序(Merge Sort)
* 利用递归方式将数组无限二分为左右分数组,直到数组中只有两个元素,将元素按照顺序放入temp数组后再覆盖原数组相应段位并返回上层,
* 此时上层数组将接收已经排序的左右分数组,重复操作(将元素按照顺序放入temp数组后再覆盖原数组相应段位并返回上层)直到最终排序完成
*/
public static void MergeSort(int[] a, int left, int right) {
if (left >= right)
return;
int mid = left + (right - left) / 2;
MergeSort(a, left, mid);
MergeSort(a, mid + 1, right);
int[] temp = new int[right - left + 1];
int i = left;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= right) {
temp[k++] = a[i] <= a[j] ? a[i++] : a[j++];
}
while (i <= mid) {
temp[k++] = a[i++];
}
while (j <= right) {
temp[k++] = a[j++];
}
for (int m = 0; m < temp.length; m++) {
a[left + m] = temp[m];
}
}
/**
* 快速排序(Quick Sort)
* 双层循环嵌套,外层循环从左向右找到第一个大于数组最后元素(基准数据)的数组位置然后进入内层循环,内层循环从右向左找到第一个小于数组最后元素的数组位置,
* 将外层循环的大元素和内层循环的小元素交换位置,这样外层循环完成会得到小元素在基准数据左侧、大元素在基准数据右侧的数组,
* 然后将基准数据左侧和基准数据右侧分别重复上述操作,直到左右不再可分最后得到排序好的数组
*/
public static void QuickSort(int[] a, int left, int right) {
if (left >= right) {
return;
}
int j = right;
for (int i = left; i < j - 1; i++) {
if (a[i] > a[right]) {
for (; j - 1 > i; j--) {
if (a[j - 1] <= a[right]) {
int bank = a[i];
a[i] = a[j - 1];
a[j - 1] = bank;
break;
}
}
}
}
if (a[right] < a[j - 1]) {
int bank = a[right];
a[right] = a[j - 1];
a[j - 1] = bank;
}
QuickSort(a, left, j - 1);
QuickSort(a, j, right);
}
/**
* 计数排序(Counting Sort)
* 遍历传入数组记录最大值、最小值,然后创建最大值-最小值+1长度的位数组,遍历原数组将元素数值当做角标存入位数组(角标为元素大小减去最小值),
* 全部放入后从低位遍历位数组将元素存回原数组(存回原数组的元素为角标加上最小值),遍历完成得到排序好的数组
*/
public static void CountingSort(int[] a) {
if (a.length <= 0) {
return;
}
int min = a[0], max = a[0];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
}
if (max < a[i]) {
max = a[i];
}
}
int[] container = new int[max - min + 1];
for (int i = 0; i < a.length; i++) {
container[a[i] - min]++;
}
int marker = 0;
for (int i = 0; i < container.length; i++) {
for (int j = 0; j < container[i]; j++, marker++) {
a[marker] = i + min;
}
}
}
/**
* 基数排序(Radix Sort)
* 遍历原数组计算数组中最大值的位数,循环内嵌子循环,外层循环执行次数为最大值位数,外层每次循环代表将对应位数开始排序(0为个位、1为十位依次排序)
* 子循环1将原数组遍历取元素相应'位'的数值(0-9)在对应count数组角标++
* 子循环2将count数组进行位置累加,这样数组中角标内元素的数值就对应了角标排序后应该所在的位置+1
* 子循环3将原数组遍历取元素相应'位'的数值(0-9)匹配count对应角标元素的值-1,这样得到此元素排序后的位置,将其赋值给新数组result
* 将新数组result覆盖原数组继续进行上述操作,直到外层循环次数等于最大数位数
* 原理:先将个位排序然后将排序后覆盖原数组,然后十位、百位...,直到最大值的所有位全部排序过,就得到了排序的数组
*/
public static void RadixSort(int[] a) {
if (a.length <= 0) {
return;
}
int max = a[0];
int[] result = new int[a.length];
for (int i = 0; i < a.length; i++) {
if (max < a[i]) {
max = a[i];
}
}
int maxDigit = String.valueOf(max).length();
for (int i = 0; i < maxDigit; i++) {
int[] count = new int[10];
int abdication = (int) Math.pow((double) 10, (double) i);
for (int j = 0; j < a.length; j++) {
int remainder = a[j] / abdication % 10;
count[remainder]++;
}
for (int j = 1; j < count.length; j++) {
count[j] = count[j] + count[j - 1];
}
for (int j = a.length - 1; j >= 0; j--) {
int num = a[j] / abdication % 10;
result[--count[num]] = a[j];
}
System.arraycopy(result, 0, a, 0, a.length);
}
}
/**
* 堆排序(Heap Sort)
* 第一个for循环从数组尾部开始向前判断此元素和父元素是否需要交换(大于父元素),如果需要置换则需要考虑置换后的子元素是否需要和子元素的子元素进行置换,
* 如果需要就持续置换,直到所有子元素满足大顶堆排列(由第一个for循环内的while完成),置换完成后继续遍历重复以上操作,遍历结束得到大顶堆数组
* 然后将堆顶元素和原数组最后一位置换,削减原数组长度(-1)并且再次侯建大顶堆,重复上述操作直到取出最后一个元素
* 原理:将原数组构建成大顶堆数据模型,这样堆顶数字就最大,并且父子元素位置有相应关系,取出数字再次构建大顶堆数据,重复操作将所有元素取出排序即完成
* 父子元素相应位置计算:左子元素角标 =2 * 父元素角标 + 1;右子元素角标 = 2 * 父元素角标 + 2;父元素角标 = (子元素角标-1)/2
*/
public static void HeapSort(int[] a, int mark) {
for (int i = --mark; i >= 0; i--) {
if (a[i] > a[(i - 1) / 2]) {
int bank = a[i];
a[i] = a[(i - 1) / 2];
a[(i - 1) / 2] = bank;
int head = i;
while ((2 * head + 1 <= mark && a[head] < a[2 * head + 1])
|| (2 * head + 2 <= mark && a[head] < a[2 * head + 2])) {
boolean rightExistence = (2 * head + 2) <= mark;
if (rightExistence && a[2 * head + 2] > a[2 * head + 1]) {
bank = a[head];
a[head] = a[2 * head + 2];
a[2 * head + 2] = bank;
head = 2 * head + 2;
} else {
bank = a[head];
a[head] = a[2 * head + 1];
a[2 * head + 1] = bank;
head = 2 * head + 1;
}
}
}
}
while (mark >= 1) {
int bank = a[0];
a[0] = a[mark];
a[mark] = bank;
mark--;
int head = 0;
while ((2 * head + 1 <= mark && a[head] < a[2 * head + 1])
|| (2 * head + 2 <= mark && a[head] < a[2 * head + 2])) {
boolean rightExistence = (2 * head + 2) <= mark;
if (rightExistence && a[2 * head + 2] > a[2 * head + 1]) {
bank = a[head];
a[head] = a[2 * head + 2];
a[2 * head + 2] = bank;
head = 2 * head + 2;
} else {
bank = a[head];
a[head] = a[2 * head + 1];
a[2 * head + 1] = bank;
head = 2 * head + 1;
}
}
}
}
/**
* 桶排序(Bucket Sort)
* 桶排序思想,将原数组按照需求分成多个区间桶,桶的区间不重合且有序,然后分别对桶内数据进行排序(可以引用其他排序方法),然后将桶按顺序拼接即得到排序的数组
*/
public static void BucketSort(int[] a) {
if (a.length <= 0) {
return;
}
int min = a[0], max = a[0];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
}
if (max < a[i]) {
max = a[i];
}
}
List<Integer> bucket1 = new ArrayList<Integer>();
List<Integer> bucket2 = new ArrayList<Integer>();
int length = (max - min) / 2 + min;
for (int i = 0; i < a.length; i++) {
if (a[i] - length < 0) {
bucket1.add(a[i]);
} else {
bucket2.add(a[i]);
}
}
Integer[] array1 = bucket1.toArray(new Integer[bucket1.size()]);
Integer[] array2 = bucket2.toArray(new Integer[bucket2.size()]);
Arrays.sort(array1);
Arrays.sort(array2);
int i = 0;
for (; i < array1.length; i++) {
a[i] = array1[i];
}
for (int j = 0; j < array2.length; i++, j++) {
a[i] = array2[j];
}
}
通过JAVA代码实现十种排序
最新推荐文章于 2024-03-07 19:55:56 发布