插入排序
图解
代码实现
public class TestDemo {
public static void main(String[] args) {
int[] array = {5,4,3,2,1}; //定义数组
insertSort(array);
System.out.println(Arrays.toString(array));
}
public static void insertSort(int[] array){
for (int i = 1; i < array.length; i++) {
int j = i - 1; //
int tmp = array[i]; // 记录i下标的值
for(;j >= 0;j--){ //从j位置往后遍历,
if(array[j] > tmp){
array[j + 1] = array[j]; //大的放到前面
}else{
break;
}
}
array[j + 1] = tmp;//最后最小的给放到前面,(j一直在减减)
}
}
}
希尔排序
图解
代码实现
public class ShellSort {
public static void main(String[] args) {
int[] array = {12,5,9,34,6,8,33,56,89,0,7,4,22,55,77};
shellSort(array);
System.out.println(Arrays.toString(array));
}
public static void shell(int[] array,int gap){
for (int i = gap; i < array.length; i++) { //先按分组排
int j = i - gap;
int tmp = array[i]; //记录i下标值
for(;j >= 0;j -= gap){
if(array[j] > tmp){
array[j + gap] = array[j]; //交换
}else{
break;
}
}
array[j + gap] = tmp; //还回去
}
}
public static void shellSort(int[] array){
int gap = array.length; //分组
while(gap > 1){ //这里是循环条件
shell(array,gap);
gap /= 2;
}
shell(array,1); //最后就是分成一组最后的排序
}
}
选择排序
图解
代码实现
public class SelectSort {
public static void main(String[] args) {
int[] array = {1,4,12,6,7};
selectSort(array);
System.out.println(Arrays.toString(array));
}
public static void selectSort(int[] array){
for (int i = 0; i < array.length; i++) {
int min = i; //记录最小的值下标
for (int j = i+1; j < array.length; j++) {
if(array[j] < array[min]){ //比较当前下标值得大小
min = j;
}
}
swap(array,i,min); //交换最小值在前面去
}
}
private static void swap(int[] array, int a, int b) { //交换函数
int tmp = array[a];
array[a] = array[b];
array[b] = tmp;
}
}
冒泡排序
图解
代码实现
public class MaoPaoSort {
public static void main(String[] args) {
int[] array = {6,12,10,3,5};
bubbleSort(array);
System.out.println(Arrays.toString(array));
}
public static void swap(int[] array,int i,int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length-1; i++) {
boolean flg = false; //优化,
for (int j = 0; j < array.length-1-i; j++) {
if(array[j] > array[j+1]) {
swap(array,j+1,j);
flg = true; //说明这里进入了交换语句,把flg改成true
}
}
if(flg == false) { //说明这里并没有进入交换语句,说明这个数组已经有序了,直接返回
break;
}
}
}
}
堆排
图解
详情见代码
代码实现
public class HeapSort {
public static void main(String[] args) {
int[] array = {27,15,19,18,28,34,65,49,25,37};
heapSort(array);
System.out.println(Arrays.toString(array));
}
public static void swap(int[] array,int i,int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
public static void heapSort(int[] array) {
//1、建堆 O(N)
createHeap(array);
int end = array.length-1;
//2、交换然后调整 O(N * log N)
while (end > 0) {
swap(array,0,end);
shiftDown(array,0,end);
end--;
}
}
public static void createHeap(int[] array) { //建堆
for (int parent = (array.length-1-1)/2; parent >= 0 ; parent--) {
shiftDown(array,parent,array.length);
}
}
public static void shiftDown(int[] array,int parent,int len) { //大根堆
int child = 2*parent+1;//左孩子下标
while (child < len) {
if(child+1 < len && array[child] < array[child+1]) {
child++;
}
//child下标 就是左右孩子最大值的下标
if(array[child] > array[parent]) {
swap(array,child,parent);
parent = child;
child = 2*parent+1;
}else {
break;
}
}
}
}
快排
图解
代码实现(挖坑法)
public class QuickSort {
public static void main(String[] args) {
int[] array = {6,1,2,7,9,3,4,5,10,8};
quickSort(array);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int[] array){ //快排
quick(array,0,array.length - 1);
}
public static void quick(int[] array,int left,int right){ //递归
if(left >= right){ //递归结束条件
return;
}
int pivot = partition(array,left,right); //基准值
quick(array,left,pivot - 1); //递归左边的
quick(array,pivot + 1,right); //递归右边的
}
public static int partition(int[] array,int start,int end){ //基准值
int tmp = array[start]; //让开始下标放到tmp中
while(start < end){ //循环条件
if(start < end && array[end] >= tmp){ //start < end是大前提,所以又要写一遍
end--;
}
array[start] = array[end]; //放到前面
if(start < end && array[start] <= tmp){
start++;
}
array[end] = array[start]; //放到后面
}
array[start] = tmp; //放回tmp值
return start; //返回下标(基准值)
}
}
优化一下这个代码,我们这样一直找第一个并不确定这个数是大是小,我们用三数取中法找到中间值与start交换后再快排.详情见代码
快排优化(三数取中法)
public class QuickSort {
public static void main(String[] args) {
int[] array = {6,1,2,7,9,3,4,5,10,8};
quickSort(array);
System.out.println(Arrays.toString(array));
}
public static void swap(int[] array,int a,int b){
int tmp = array[a];
array[a] = array[b];
array[b] = tmp;
}
public static void quickSort(int[] array){ //快排
quick(array,0,array.length - 1);
}
public static void quick(int[] array,int left,int right){ //递归
if(left >= right){ //递归结束条件
return;
}
//1、找基准之前,我们找到中间大小的值-使用三数取中法
int midValIndex = findMidValIndex(array,left,right); //这样有可能大大提升了代码的效率
swap(array,midValIndex,left);
int pivot = partition(array,left,right); //基准值
quick(array,left,pivot - 1); //递归左边的
quick(array,pivot + 1,right); //递归右边的
}
private static int findMidValIndex(int[] array,int start,int end) { //找到这三个数的中间值
int mid = start + ((end-start) >>> 1); //(start + end) / 2;
if(array[start] < array[end]) {
if(array[mid] < array[start]) {
return start;
}else if(array[mid] > array[end]) {
return end;
}else {
return mid;
}
}else {
if(array[mid] > array[start]) {
return start;
}else if(array[mid] < array[end]) {
return end;
}else {
return mid;
}
}
}
public static int partition(int[] array,int start,int end){ //基准值
int tmp = array[start]; //让开始下标放到tmp中
while(start < end){ //循环条件
if(start < end && array[end] >= tmp){ //start < end是大前提,所以又要写一遍
end--;
}
array[start] = array[end]; //放到前面
if(start < end && array[start] <= tmp){
start++;
}
array[end] = array[start]; //放到后面
}
array[start] = tmp; //放回tmp值
return start; //返回下标(基准值)
}
}
非递归实现
public class Demo1 {
public static void main(String[] args) {
int[] array = {6,1,2,7,9,3,4,5,10,8};
quickSort(array);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int[] array) {
Stack<Integer> stack = new Stack<>();
int left = 0;
int right = array.length - 1;
int pivot = partiton(array, left, right); //基准值
if (pivot > left + 1) { //左边是不是只有一个了
stack.push(left);
stack.push(pivot - 1);
}
if (pivot < right - 1) {
stack.push(pivot + 1);
stack.push(right);
}
while (!stack.isEmpty()) {
right = stack.pop(); //新的右下标
left = stack.pop(); //新的左下标
pivot = partiton(array, left, right); //新的基准值
if (pivot > left + 1) {
stack.push(left);
stack.push(pivot - 1);
}
if (pivot < right - 1) {
stack.push(pivot + 1);
stack.push(right);
}
}
}
public static int partiton(int[] array, int start, int end) {
int tmp = array[start];
while (start < end) {
while (start < end && array[end] >= tmp) {
end--;
}
array[start] = array[end];
while (start < end && array[start] <= tmp) {
start++;
}
array[end] = array[start];
}
array[start] = tmp;
return start;
}
}
归并排序
代码实现
import java.util.Arrays;
public class Demo4 {
/*
* 时间复杂度:N * log2 N
* 空间复杂丢:O(N)
* 稳定性:稳定
* */
public static int[] mergeSort(int[] array){
if(array == null){
return array;
}
mergeSortFunc(array,0,array.length-1);
return array;
}
private static void mergeSortFunc(int[] array,int low,int high){
if(low >= high){
return;
}
// int mid = (high + low) >>> 1
int mid = low + ((high - low) >>> 1);
mergeSortFunc(array,low,mid);// 左边
mergeSortFunc(array,mid+1,high);// 右边
merge(array,low,mid,high);
}
private static void merge(int[] array,int low,int mid,int high){
int[] arr = new int[high - low +1];
int start1 = low;
int end1 = mid;
int start2 = mid+1;
int end2 = high;
int i = 0;
while (start1 <= end1 && start2 <= end2){
if(array[start1] > array[start2]){
arr[i++] = array[start2++];
}else{
arr[i++] = array[start1++];
}
}
while(start1 <= end1){
arr[i++] = array[start1++];
}
while(start2 <= end2){
arr[i++] = array[start2++];
}
for (int j = 0; j < arr.length; j++) {
array[low++] = arr[j];
}
}
public static void main(String[] args) {
int[] array = {1,6,7,10,2,3,4,9};
mergeSort(array);
System.out.println(Arrays.toString(array));
}
}
非递归
import java.util.Arrays;
public class MergeSortNonRecursion {
public static void mergeSort(int[] array){
//归并排序非递归实现
int groupNum = 1;// 每组的数据个数
while(groupNum < array.length){
// 无论数组含有几个元素, 数组每次都需要从下标 0位置,开始遍历。
for(int i = 0;i<array.length;i+= groupNum * 2){
int low = i;
int mid = low + groupNum -1;
// 防止越界【每组的元素个数,超过了数组的长度】
if(mid >= array.length){
mid = array.length-1;
}
int high = mid + groupNum;
// 防止越界【超过了数组的长度】
if(high >= array.length){
high = array.length-1;
}
merge(array,low,mid,high);
}
groupNum *= 2;//每组的元素个数扩大到原先的两倍。
}
}
public static void merge(int[] array,int low,int mid,int high){
// high 与 mid 相遇,说明 此时数组分组只有一组,也就说没有另一组的数组与其合并
// 即数组已经有序了,程序不用再往下走。
if(high == mid){
return;
}
int[] arr = new int[high -low + 1];
int start1 = low;
int end1 = mid;
int start2 = mid+1;
int end2 = high;
int i = 0;
while(start1 <= end1 && start2 <= end2){
if(array[start1]>array[start2]){
arr[i++] = array[start2++];
}else{
arr[i++] = array[start1++];
}
}
while (start1 <= end1){
arr[i++] = array[start1++];
}
while(start2 <= end2){
arr[i++] = array[start2++];
}
for (int j = 0; j < arr.length; j++) {
array[low++] = arr[j];
}
}
public static void main(String[] args) {
int[] array = {12,5,8,7,3,4,1,10};
mergeSort(array);
System.out.println(Arrays.toString(array));
}
}