给定一个数组,从小到大排序
package BubbleSort;
/**
* 冒泡排序
*/
public class BubbleSort {
public static int[] bullueSort(int[] array) {
if (array.length == 0) {
return array;
}
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length - 1; j++) {
if (array[j + 1] < array[j]) {
int temp = array[j + 1];
array[j + 1] = array[j];
array[j] = temp;
}
}
}
return array;
}
public static void main(String[] args) {
int [] arr = {0,41,5,5,866,47};
int [] sorted = bullueSort(arr);
for (int i:sorted
) {
System.out.print(i+" ");
}
}
}
package SelectionSort;
/**
* 选择排序
*/
public class selectionSort {
public static int[] selectionSort(int[]array){
if(array.length == 0){
return array;
}
for(int i=0;i<array.length;i++){
int minIndex = i;
for(int j=i;j<array.length;j++){
if(array[j]<array[minIndex]){//寻找最小的数
minIndex = j;//保存最小值的角标
}
/**
* 交换最小值与无序序列的第一位
*/
int temp =array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
}
return array;
}
public static void main(String[] args) {
int [] arr = {0,41,45,5,45,47};
int [] sorted = selectionSort(arr);
System.out.println("选择排序如下:");
for (int i:sorted
) {
System.out.print(i+" ");
}
}
}
package InsertionSort;
/**
* 插入排序
*/
public class InsertionSort {
public static int[] insertionSort(int[] array){
if(array.length == 0){
return array;
}
int current;
for (int i =0;i<array.length-1;i++){
current =array[i+1];
int preIndex =i;
while (preIndex>=0&¤t<array[preIndex]){//保证preIndex>0,确保数组不会越界
array[preIndex+1] =array[preIndex];
preIndex--; //向前寻找小于等于当前元素的值
}
array[preIndex+1]= current;
}
return array;
}
public static void main(String[] args) {
int [] arr = {0,41,45,5,45,47};
int [] sorted = insertionSort(arr);
System.out.println("插入排序如下:");
for (int i:sorted
) {
System.out.print(i+" ");
}
}
}
算法背景:希尔排序是Donald Shell 于1959年提出的一种排序算法。希尔排序也是一种插入排序,所以想要掌握希尔排序,首先要了解插入排序,请会上文排序算法三。希尔排序是简单插入排序经过改进后的一个更加高效的版本,也称为缩小增量排序。其是时间效率是突破O(N**2)的第一批算法之一。
·
希尔排序把数据序列按照一定的增量进行分组,对每组使用直接插入排序算法;随着增量逐渐减少,每组包含的关键词原来越少,当增量减到1️⃣的时候,整个序列就会被分成一组,进行插入排序,算法便终止了
package ShellSort;
/**
* 希尔排序
*/
public class ShellSort {
public static int[] shellSort(int[]array){
if(array.length==0){
// System.out.println("数组为空");
return array;
}
int len = array.length;
int temp,gap = len/2;
while (gap>0){
for (int i = gap; i <len ; i++) {
temp = array[i];
int preIndex =i-gap;
while (preIndex>=0&&array[preIndex]>temp){//分组交换,(插入排序)
array[preIndex+gap]=array[preIndex];
preIndex -= gap;
}
array[preIndex+gap] = temp;
}
gap/=2;//缩小步长,继续跳入第一层while 循环
}
return array;
}
public static void main(String[] args) {
int [] arr = {465,56,4,4,5,334,7,7,165};
int [] sorted = shellSort(arr);
System.out.println("希尔排序如下:");
for (int i:sorted
) {
System.out.print(i+" ");
}
}
}
算法背景:和选择排序一样,归并排序的性能不受输入数据的影响,但是其时间性能的表现比选择排序好的多,始终为O(nlog n)但是其代价是需要额外的内存空间
·
归并排序是采用分治法的一个非常典型的应用,归并排序是一种稳定的排序算法,将已经有序的序列进行合并,得到完全有序的序列。
·
因为较难理解 ,此处整一个讲得很好的B站视频链接:归并排序
package MergeSort;
import java.util.Arrays;
/**
* 归并排序
*/
public class MergeSort {
public static int[] mergeSort(int[]array){
if(array.length<2){
return array;
}
int mid = array.length/2;
int []left = Arrays.copyOfRange(array,0,mid);
int []right = Arrays.copyOfRange(array,mid,array.length);
return merge(mergeSort(left),mergeSort(right));
}
/**
*
* 归并排序--将 两段排序好的数组合成一个排序数组
*
*/
public static int[]merge(int[]left,int[]right){
int[] result = new int[left.length+right.length];//新建一个可以容纳左右数组的新数组
//两个自列的归并过程
for (int index = 0,i=0,j=0;index<result.length;index++){
if(i>=left.length){
result[index]=right[j++];
}else if(j>=right.length){
result[index] = left[i++];
}else if(left[i]>right[j]){
result[index]=right[j++];
}else {
result[index]=left[i++];
}
}
return result;
}
public static void main(String[] args) {
int [] arr = {465,56,4,4,5,334,7,7,165};
int [] sorted = mergeSort(arr);
System.out.println("归并排序如下:");
for (int i:sorted
) {
System.out.print(i+" ");
}
}
}
算法背景:快速排序通过一趟排序将序列分割成独立的两部分,其中一部分均比关键字小,一部分均比关键字大,然后对分割出来的两部分继续进行快速排序的递归调用,以达到使整个序列有序的目的
package QuickSort;
/**
* 快速排序方法
*/
public class QuickSort {
public static void quickSort(int[] array, int left, int right) {
//如果左边的索引大于右边的索引,出现错误,直接退出该排序方法
if (left > right) {
return;
}
//确定基准数,以最左开始
int base = array[left];
int i = left;
int j = right;
while (i != j) {
while (array[j] >= base && i < j) {
j--;
}
while (array[i] <= base && i < j) {
i++;
}
//代码走到这里意味着在基准条件下找到了符合条件的元素,交换他们
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
//i=j此时索引走到一起,交换基准数和相遇位置元素
array[left] = array[i];
array[i] = base;
//一趟快排后继续排左边
quickSort(array, left, j - 1);
quickSort(array, j + 1, right);
}
public static void main(String[] args) {
int[] arr = { 0, 41, 45, 5, 45, 47};
quickSort(arr, 0, arr.length - 1);
for (int i : arr
) {
System.out.print(i + " ");
}
}
}
堆排序是指利用堆这种数据结构所设计的排序算法。堆是一个近似于完全二叉树的结构,同时满足其自身子节点键值或索引总是小于或大于其父节点
此处墙裂推荐B站良心up视频:传送门
//代码注释很详细,有助于理解
package HeapSort;
/**
* 堆排序
*/
public class HeapSort {
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private static void heapify(int[] tree, int n, int i) {
if (i >= n) {//如果根节点大于节点的个数,直接跳出,结束递归
return;
}
int c1 = 2 * i + 1; //当前选定根节点的左子节点
int c2 = 2 * i + 2; //当前选定根节点的右子节点
int max = i; //假定当前根节点是该子堆的最大值
// * 找出子堆中的最大值,交换index
if (c1 < n && tree[c1] > tree[max]) {
max = c1; //如果左子节点大于根节点元素,交换其下标
}
if (c2 < n && tree[c2] > tree[max]) {
max = c2; //如果右子节点大于子堆中最大值,交换下标
}
if (max != i) {//如果最大值不是根节点,交换找到的最大值和根节点元素
swap(tree, max, i);//交换函数
heapify(tree, n, max); //递归做heapify,此时如果在主函数中 进行调用只对指定根节点的子堆进行heapifY操作
}
}
/**
* 对任意数组建立大顶堆
*
* @param tree
* @param n
*/
private static void build_heap(int[] tree, int n) {
int last_node = n - 1;//找出完全二叉树的最后一个节点
int parent = (last_node - 1) / 2;//找出最后一个节点的父节点
for (int i = parent; i >= 0; i--) {//对树中的所有父节点进行遍历并heapify来得到根节点最大的堆
heapify(tree, n, i);
}
}
private static void heap_sort(int[] tree, int n) {
build_heap(tree, n);//把数组建立成一个大顶堆
int i;
for (i = n - 1; i >= 0; i--) {
swap(tree, i, 0);//遍历节点交换最后一个元素和堆最顶端根节点元素
heapify(tree, i, 0);//交换完成后相当于拿走交换的根节点(最大)再进行heapify操作
}
}
public static void main(String[] args) {
int[] arr = {4, 5, 8, 2, 10, 2};
heap_sort(arr, arr.length);//heapsort操作后遍历,就相当于从小到大遍历数组
for (int i : arr) {
System.out.println(i);
}
}
}
package CountingSort;
import java.util.Arrays;
public class CountSort {
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);//初始化数组,使用Arrays 将初始值0全部复制,省略了繁琐的for循环
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++; //如果将新数组i索引上的计数清零,就将新数组下标i索引+1
}
}
return array;//返回重新填充的待排序数组 ,此时该数组已经有序
}
public static void main(String[] args) {
int [] arr = {2,4,8,5,3};
int [] sorted = CountingSort(arr);
for (int i:sorted
) {
System.out.print(i+" ");
}
}
}