1.冒泡排序BubbleSort
2.快速排序QuickSoet
3.插入排序InsertSort
4.希尔排序ShellSort
5.选择排序SelectSort
6.归并排序MergeSort
7.基数排序RadixSort
8.队列排序RadixQueueSort
9.堆排序HeapSort
1.BubbleSort
package cn.DataStructureAndAlgorithms.Ravanla.copy;
import java.util.Arrays;
/*
* 冒泡排序
*/
public class TestBubbleSort {
public static void main(String[] args) {
int[] arr1 = new int[] {5, 7, 4, 3, 7, 3, 9, 1, 0};
bubbleSort(arr1);
System.out.println(Arrays.toString(arr1));
}
public static void bubbleSort(int[] arr) {
for(int i = 0; i < arr.length-1; i++) {
for(int j = 0; j < arr.length - 1 - i; j++) {
if(arr[j] > arr[j + 1]){
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
//BubbleSort在我的博客中另一篇文章有详细的介绍
//
2.QuickSort
package cn.DataStructureAndAlgorithms.Ravanla.copy;
import java.util.Arrays;
/*
* 快速排序
* @author Ravanla
* 思路:
* 1.需要形参有开头start和结尾end
* 2.如果start < end就递归自己
* 3.把下标为0(也可以是其他下标)的值设为标准值
* 把开头和结束分别设置为低位(low)和高位(high)
* 4.当low<high时循环执行
* 1.(low<high时)高位的值大于标准值,把高位减一位,直到小于时把当前高位的值赋值给低位
* 2.(low<high时)低位的值小于标准值,把低位减一位,直到大于时把当前低位的值赋值给高位
* 5.执行完后此时的高位和低位相等,把标准值赋值给低位or高位的值
* (low<high时)保证高位一定等于低位出循环
* 6.此时的数组分为(low右边)大于标准值和(low左边)小于标准值
* 然后分两边递归调用自己
* 7.直到start >= end(low >= high)不会递归下去
*/
public class TestQuickSort {
public static void main(String[] args) {
int[] arr2 = new int[] {5, 7, 4, 3, 7, 3, 9, 1, 0};
System.out.println(Arrays.toString(arr2));
QuickSort(arr2, 0, arr2.length - 1);
System.out.println(Arrays.toString(arr2));
}
public static void QuickSort(int[] arr,int start, int end){
if(start < end){
int low = start;
int high = end;
int standard = arr[low];
while(low < high){
while(low < high && standard < arr[high])high--;
if(low < high) arr[low++] = arr[high];
while(low < high && standard > arr[low])low++;
if(low < high) arr[high--] = arr[low];
}
arr[low] = standard;
QuickSort(arr, start, low - 1);
QuickSort(arr, low + 1, end);
}
}
}
3.InsertSort
package cn.DataStructureAndAlgorithms.Ravanla.copy;
/**
*
* @author Ravanla
* 思路:
* 1.设置i从1开始遍历全数组
* 1.如果下标i的值小于前(左)一个数
* 1.把下标i的值赋值给temp
* 2.设置j为i的前(左)一个下标
* 1.如果temp还是小于下标为j的值,将下标j的值赋值给j后面(右)一个下标
* 并将j指向前(左)一个下标
* 3.把temp赋值给j后面(右)一个下标
*/
import java.util.Arrays;
public class TestInsertSort {
public static void main(String[] args) {
int[] arr = new int[] {5, 7, 4, 3, 7, 3, 9, 1, 0};
insertSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void insertSort(int[] arr) {
for(int i = 1; i < arr.length; i++) {
if(arr[i] < arr[i - 1]) {
int temp = arr[i];
int j;
for(j = i - 1; j >= 0 && temp < arr[j]; j--) {
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
}
}
}
4.ShellSort
package cn.DataStructureAndAlgorithms.Ravanla.copy;
import java.util.Arrays;
/*
* 希尔排序
* @author Ravanla
* 思路:
* 1.设置一个增量s,记录每次arr的长度除以2的值
* 1.设置一个i等于这个s,i从这个数组的一半开始每次循环加一
* 1.设置一个j等于i - s,每次减s个增量,减到小于0为止
* 1.在这里进行下标i和下标j的值的对比
* 当增量序列为dlta[k]=2t-k+1-1(0≤k≤t≤⌊log2(n+1)⌋)时,可以获得不错的效率
*/
public class TestShellSort {
public static void main(String[] args) {
int[] arr = new int[] {5, 7, 4, 3, 7, 3, 9, 1, 0};
System.out.println(Arrays.toString(arr));
ShellSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void ShellSort(int[] arr) {
for(int s = arr.length/2; s > 0; s/=2) {
//s
for(int i = s; i < arr.length; i++) {
// for(int j = i - s; j < arr.length; j+=s)
for(int j = i - s; j >= 0; j-=s){
//第一次的i - s就等于0 表示arr[j]从数组下标零开始
//每隔s个位置经行比较
//之后的i - s
if(arr[i] < arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
}
}
5.SelectSort
package cn.DataStructureAndAlgorithms.Ravanla.copy;
/*
* 选择排序
* 思路:
* 1.遍历全数组
* 2.把下标为0设为最小值的下标,并开始遍历该下标以后是否有比它小的元素,
* 如果有把该下标设为最小值的小标
* 3.把最小值的小标与遍历到当前下标的i的值 调换
*/
import java.util.Arrays;
public class TestSelectSort {
public static void main(String[] args) {
int[] arr = new int[] {5, 7, 4, 3, 7, 3, 9, 1, 0};
System.out.println(Arrays.toString(arr));
SelectSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void SelectSort(int[] arr) {
for(int i = 0; i < arr.length; i++) {
int min = i;
for(int j = i + 1; j < arr.length; j++) {
if(arr[min] > arr[j]) {
// int temp = arr[min];
// arr[min] = arr[j];
// arr[j] = temp;
min = j;
}
}
if(i != min) {
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
}
}
6.MergeSort
package cn.DataStructureAndAlgorithms.Ravanla.copy;
import java.util.Arrays;
//归并排序
/**
*
* @author Ravanla
* 思路:
* merge(归并)函数
* 1.把一个数组想象成两个等份(相差不过1)的数组 左边的低位(i = low)到高位(middle)
* 右边的低位(j = middle + 1)到高位(high)
* 2.设置index指向装入下标
* 3.设置备份数组,数组长度由递归过来的数组的长度决定,
* 因为high=arr.length-1传过来的-1,在保证temp数组与传入的数组长度一样,所以要+1
* 4.在两边数组的低位都还没超过(相应的)高位的情况下经行比较,
* 把小(或大)的放在temp左(或右)边
* index(从0到arr.length/2)指向放入位置的下标
* 5.把还没超过(相应的)高位的数组,把剩下的数依次放入temp数组直到遍历到(相应的)高位为止
* 6.剩下一个步骤要结合mergeSort函数来理解
*
* mergeSort(递归调用归并函数)函数
* 1.在低位低于高位的情况下
* 2.设置middle
* 3.递归自己(把子拆成等分[相差不过1]的两半,递归调用)
* 4.最后调用归并函数-------------看到这里可以理解为
* 一个数组以每两个元素分成一组,每一组都经行大小比较
* 一轮结束后每四个元素分为一组....
* 所以merge函数的最后一步这样理解比较好
* arr下标 0 和 1 2 和 3 4和5
* value值 4 3 2 1
* low high | low high
* temp的下标 0 和 1 | 0 和 1
* temp数组的元素 3 4 | 1 2
*
*/
public class TestMergeSort {
public static void main(String[] args) {
int[] arr = new int[] {5, 7, 4, 3, 7, 3, 9, 1, 0};
System.out.println(Arrays.toString(arr));
mergeSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
//先看merge函数
}
public static void mergeSort(int[] arr, int low, int high) {
int middle = (high + low)/2;
if(low < high) {
mergeSort(arr, low, middle);
mergeSort(arr, middle + 1, high);
//把一个数组分成两份 然后进行归并递归调用 直到low<high结束调用
merge(arr, low, middle, high);
}
}
public static void merge(int[] arr, int low, int middle, int high) {
//low middle high
// 5, 7, 4, 3, 7, 3, 9, 1, 0
int i = low;
int j = middle + 1;
int index = 0;
int[] temp = new int[high - low + 1];
//这个临时数组的长度为high - low + 1 high传进来时是length-1
// while(i < j && j < arr.length)
while(i <= middle && j <= high){
//把一个数组分成两个数组进行比较
if(arr[i] <= arr[j]) {
temp[index] = arr[i];
i++;
index++;
}
else {
temp[index] = arr[j];
j++;
index++;
}
//把分成的两数组中最小的数依次放入temp
}
//两数组中较大的数赋值给剩下一半数组长度的temp
while(i <= middle) {
temp[index] =arr[i];
i++;
index++;
}
while(j <= high) {
temp[index] = arr[j];
j++;
index++;
}
//然后把temp归并好的数传给arr
// for(int k = 0; k <= high; k++) {
// arr[k + low] = temp[k];
//}
//arr.length - 1 -> high
//temp.length -> (high - low + 1)
//思考为什么上面一个写法会错
for(int k = 0; k < temp.length; k++) {
arr[k + low] = temp[k];
//下次归并时low会变
}
//这就归并好一次啦
//然后利用mergeSort递归调用它
}
}
//明天续更,今晚充能
7.RadixSort
package cn.DataStructureAndAlgorithms.Ravanla.copy;
import java.util.Arrays;
public class TestRadixSort {
public static void main(String[] args) {
int[] arr = new int[] {53, 274, 4, 43, 7, 3, 239, 141, 43, 2};
RadixSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void RadixSort(int[] arr) {
int max = Integer.MIN_VALUE;
//最大值为Integer.MAX_VALUE,即2147483647,最小值为Integer.MIN_VALUE
//-2147483648
//找到数组中的最大值
for(int i = 0; i < arr.length; i++) {
if(arr[i] > max) {
max = arr[i];
}
}
int maxlength = (max + "").length();
//将最大的数变为字符串,求字符串长度,此时的长度为数位大小
//https://baike.baidu.com/item/%E6%95%B0%E4%BD%8D/6157143?fr=aladdin
int[][] temp = new int[10][arr.length];
//第一次找到274,百位为2,2放在temp
int[] count = new int[10] ;
for(int i = 0, n = 1; i < maxlength; i++, n*=10) {
for(int j = 0; j < arr.length; j++) {
int ys = (arr[j]/n)%10;
temp[ys][count[ys]] = arr[j];
count[ys]++;
//看图
}
// if(i == 0) {
// for(int[] nums:temp) {
// System.out.println(Arrays.toString(nums));
// }
// System.out.println(Arrays.toString(count));
// }
int index = 0;
for(int k = 0; k < count.length; k++) {
//遍历0,1,2,3,4..., 9
if(count[k] != 0) {
for(int o = 0; o < count[k]; o++) {
//遍历count的数
arr[index] = temp[k][o];
index++;
}
//每一次遍历完将当前计数设置为0,以便下次计数为0时不会记录相同的数
count[k] = 0;
}
}
}
}
}
8.RadixQueueSort 有错误 基数队列排列先不看
package cn.DataStructureAndAlgorithms.Ravanla;
import java.util.Arrays;
/*
* 测试基数排序之队列方法
*/
public class TestRadixQueueSort {
public static void main(String[] args) {
int[] arr = new int[10];
Queue q = new Queue(arr);
//长度溢出
q.offer(2);
q.offer(3);
q.offer(4);
q.offer(5);
q.offer(6);
q.peek(arr);
}
}
class Queue{
int[] arr1 = new int[15];
public Queue(int[] arr1) {
this.arr1 = arr1;
}
// poll弹出首个元素 remove
// 查看元素peek element
// offer在尾部添加 add
// 前面的单词在异常时都会返回一个值 ,后面的则会抛出异常
public int poll() {
int a = arr1[0];
int[] temp = new int[arr1.length - 1];
for(int i = 0; i < arr1.length - 1; i++) {
temp[i] = arr1[i + 1];
}
arr1 = temp;
return a;
}
public void offer(int a) {
int[] temp = new int[arr1.length + 1];
for(int i = 0; i < arr1.length + 1; i++) {
//下面这个语句错误的
temp[i + 1] = arr1[i];
}
temp[0] = a;
arr1 = temp;
}
public void peek(int[] arr) {
System.out.println(Arrays.toString(arr));
}
}
9.HeapSort
下面数组所表达的是二叉树的排序,但是这个二叉树有点乱,接下来将它排序
package cn.DataStructureAndAlgorithms.Ravanla.copy;
import java.util.Arrays;
public class TestHeapSort {
public static void main(String[] args) {
int[] arr = new int[] {5, 7, 4, 3, 7, 3, 9, 1, 0};
int start = (arr.length - 1)/2;
HeapSort p = new HeapSort();
p.arr = arr;
p.size = arr.length;
for(int i = start; i >= 0; i--) {
p.index = i;
p.MaxHeap(i);
// 这里有缺陷,但是不知道怎么改会比较好
}
for(int j = arr.length - 1; j >=0; j--) {
int temp = arr[0];
arr[0] = arr[j];
arr[j] = temp;
p.size = j;
p.MaxHeap(0);
}
System.out.println(Arrays.toString(arr));
}
}
排成大顶堆后,将大顶堆的根放在最后,然后继续排
package cn.DataStructureAndAlgorithms.Ravanla.copy;
public class HeapSort {
int[] arr = new int[8];
// 这里缺陷非常明显,不够灵活
int size;
int index;
public HeapSort() {
}
// public HeapSort(int[] arr, int size, int index) {
// this.arr = arr;
// this.size = size;
// this.index = index;
// }
public void MaxHeap(int index) {
int leftNode = 2 * index + 1;
int rightNode = 2 * index + 2;
int max = index;
// if(leftNode < size && arr[leftNode] > arr[max]) {
// int temp = arr[leftNode];
// arr[leftNode] = max;
// arr[max] = temp;
// }
// if(rightNode < size && arr[rightNode] > arr[max]) {
// int temp = arr[rightNode];
// arr[rightNode] = max;
// arr[max] = temp;
// }
if(leftNode < size && arr[leftNode] > arr[max]) {
max = leftNode;
}
if(rightNode < size && arr[rightNode] > arr[max]) {
max = rightNode;
}
if(max != index) {
int temp = arr[max];
arr[max] = arr[index];
arr[index] = temp;
MaxHeap(max);
}
}
public void heapSort(int[] arr) {
}
}