冒泡排序
冒泡排序的思路:
冒泡需要两个for循环:外面的for循环表示需要循环的次数,为数组的长度,里层的for循环是来选择数组中的最大值。
比如第一个循环后,最大的数就被排到数组的最后面,第二个循环后,第二大的数就被选出来排到后面。。。。等等,完成排序。
代码
package com.wuxudong.sort;
import java.util.Arrays;
//冒泡排序
public class BubbleSort {
public static void main(String[] args) {
//定义数组
int [] arr=new int []{1,3,2,45,3,24,25};
//定义排序方法
bubbleSort(arr);
//输出数组
System.out.println(Arrays.toString(arr));
}
private static void bubbleSort(int[] arr) {
for (int i = 0; i <arr.length ; i++) {
for (int j=0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
int temp;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
}
快速排序
思路:选择一个标准值,将数组中比标准数大的排到数组的后面,比标准数小的排到数组的前面,然后利用递归完成排序。
举个例子:对于这样一个数组我们选取3为标准值,并取两个指针用于遍历
start表示数组开始排序的位置,end表示数组结束排序的位置。
//定义两个位置点,高和低
int low=start;
int high=end;
//定义标准点
int stard=arr[low];
- 判断arr[high]=6>3
这时候满足条件,无需交换数的位置。并把high的指针往前移动一格
while (low<high&&stard<=arr[high]){
high=high-1;
}
2. 判断arr[high]❤️
这是不满足条件,需要把3替换成2.
arr[low]=arr[high];
3. 移动low指针 判断arr[low]=5>3,不满足条件将high指针的2替换成5
while (low<high&&arr[low]<=stard){
low++;
}
arr[high]=arr[low];
然后,high指针向前移一步。判断arr[high]=1<3,不满足条件
移动low指针,判断arr[low]=8>3不满足条件,arr[high]=arr[low]
移动high指针,判断arr[high]=5>3满足条件。再移动high指针arr[high]=9>3,满足条件。在移动指针arr[high]=8>3,满足条件。此时low==high,循环结束。并将标准值赋值给arr[low]
arr[low]=stard;
至此,我们可以看出整个数组被分为两部分,比3小的和比3大的。
这时,我们调用递归,分别对这两部分进行排序
//递归
quickSort(arr,start,low);
quickSort(arr,low+1,end);
递归结束的条件是start<end
整个代码
package com.wuxudong.sort;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int [] arr=new int []{4,3,2,45,3,24,25};
//启用排序方法
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
private static void quickSort(int[] arr, int start, int end) {
if(start<end){
//定义两个位置点,高和低
int low=start;
int high=end;
//定义标准店
int stard=arr[low];
//循环
while (low<high){
while (low<high&&stard<=arr[high]){
high=high-1;
}
arr[low]=arr[high];
while (low<high&&arr[low]<=stard){
low++;
}
arr[high]=arr[low];
}
arr[low]=stard;
//递归
quickSort(arr,start,low);
quickSort(arr,low+1,end);
}
}
}
插入排序
package com.wuxudong.sort;
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
//定义数组
int [] arr=new int []{3,3,2,45,3,24,34,67,1,25};
insertSort(arr);
System.out.println(Arrays.toString(arr));
}
private 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=0;
for (j=i-1;j>=0&&temp<arr[j];j--){
//如果前一个数比临时变量大,则需要往后移一个位置
arr[j+1]=arr[j];
}
//如果前面的数比临时变量小,则循环结束,将临时值赋值给前面数的后面一个位置
arr[j+1]=temp;
}
}
}
}
希尔排序
希尔排序是对插入排序的优化,因为在插入排序中较小的数再后面的话,需要交换很多次,才能将它移动数组前面,较大的数也是同理,因此,希尔排序通过定义步长来进行分组插入排序,可以先将较小的数快速的放到前面,较大的数快速的放到后面。
package com.wuxudong.sort;
import java.util.Arrays;
//希尔排序
public class ShellSort {
public static void main(String[] args) {
int [] arr=new int []{3,3,2,45,3,24,34,67,1,25};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void shellSort(int[] arr) {
//遍历所有步长
for (int d=arr.length/2;d>0;d=d/2){
//对分组后的数组进行插入排序
for (int i = d; i <arr.length ; i++) {
for (int j=i-d;j>=0;j=j-d){
if(arr[j]>arr[j+d]){
int temp=arr[j];
arr[j]=arr[j+d];
arr[j+d]=temp;
}
}
}
}
}
}
选择排序
思路与冒泡相同,冒泡选的是最大的,选择选的是最小的
package com.wuxudong.sort;
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int [] arr=new int [] {3,3,2,45,3,24,34,67,1,25};
selectSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void selectSort(int[] arr) {
for (int i=0;i<arr.length;i++){
int minIndex=i;
for (int j=i+1;j<arr.length;j++){
//找出最小的数
if (arr[j]<arr[minIndex]){
minIndex=j;
}
}
if(i!=minIndex){
int temp=arr[i];
arr[i]=arr[minIndex];
arr[minIndex]=temp;
}
}
}
}
归并排序
归并排序里利用了归并的思想,即将两个排序好的数组按大小归并到一个数组中。利用递归的思想,将数组差分成不可再分两个数,这两个数可以看作两个排好序的数组,进行归并,最后将递归将其它的数进行归并,完成排序。
package com.wuxudong.sort;
import java.util.Arrays;
//归并排序
public class MergeSort{
public static void main(String[] args) {
int [] arr=new int[]{3,3,2,45,3,24,34,67,1,25};
mergeSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
private static void mergeSort(int[] arr, int low, int high) {
if(low<high){
int middle=(low+high)/2;
mergeSort(arr,low,middle);
mergeSort(arr,middle+1,high);
merge(arr,low,middle,high);
}
}
//归并方法
/**
*
* @param arr 传入的数组
* @param low 第一个数组开始的下标
* @param middle 第一个数组结束的下标
* @param high 第二个数组结束的下标
*/
public static void merge(int [] arr,int low,int middle,int high){
//新建一个临时数组,用来存储归并后的数组
int [] temp=new int [high-low+1];
//记录第一个数组中需要遍历的下标
int i=low;
//记录第二个数组中需要遍历的下标
int j=middle+1;
//临时数组的下标
int index=0;
//遍历两个数组取出最小的数字,放入临时数组中
while (i<=middle&&j<=high){
if(arr[i]<=arr[j]){
//第一个数组中的值小
temp[index]=arr[i];
i++;
}else {
//第一个数组中的值大
temp[index]=arr[j];
j++;
}
index++;
}
//将剩余的数添加到临时数组中
if(i>middle) {
//第一个数组遍历完了
while (j <= high) {
temp[index] = arr[j];
j++;
index++;
}
}
if (j>high) {
//第二个数组遍历完了
while (i <= middle) {
temp[index] = arr[i];
i++;
index++;
}
}
//将临时数组的值赋值给原数组
for (int k = 0; k <temp.length ; k++) {
arr[k+low]=temp[k];
}
}
}
基数排序
基数排序的思想比较简单,实际上就是按照先较个位,再比较十位等等的思想来进行排序。
举个例子
对于这样一个数组,我们先找出其中的最大值798,并判断它是几位数,是几位数我们就要循环几次。
第一次循环:将个位数是几的数放到对应几的数组中
然后将数组里的这些数依次按照存入的顺序取出来
第二次循环:将十位数是几的数放到对应几的数组中
然后再依次取出来
第三次循环:将百位数是几的数放到对应几的数组中
最后,依次取出来完成排序
代码:
package com.wuxudong.sort;
import java.util.Arrays;
//基数排序
public class RadixSort {
public static void main(String[] args) {
int [] arr=new int [] {23,6,189,45,9,287,56,1,798,35,65,652,5};
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void radixSort(int [] arr){
int maxValue=Integer.MIN_VALUE;
//第一步:找出数组中最大的数字
for (int i=0;i<arr.length;i++){
if(arr[i]>maxValue){
maxValue=arr[i];
}
}
//得到最大数是几位数
int num=(maxValue+"").length();
//定义二维数组存储变量值
int [][] temp=new int[10][arr.length];
//定义一个数组来表示存入数组的个数
int [] counts=new int [10];
//循环遍历,循环的次数,n用来取个位,十位,百位。
for (int i = 0,n=1; i < num; i++,n=n*10) {
//循环遍历数组
for (int j=0;j<arr.length;j++){
int ys=arr[j]/n%10;
temp[ys][counts[ys]]=arr[j];
counts[ys]++;
}
//定义一个变量表示原数组的下标
int index=0;
//取出对应的元素
for (int k=0;k<10;k++){
if(counts[k]!=0){
for (int l=0;l<counts[k];l++){
arr[index]=temp[k][l];
index++;
}
//将数量置为0,留着给下个循环使用
counts[k]=0;
}
}
}
}
}
堆排序
利用了二叉树的数据结构。任何一个数组都可以表示为一个唯一的完全二叉树,任何一个完全二叉树都可以表示为一个数组。我们将数组表示为一个二叉树,然后对把这个二叉树转成大顶堆(即父节点大于子节点),这样根节点就是数组中最大的数,我们在将二叉树的最后一个叶子节点和根节点进行交换,在转为大顶堆,这个第二大的数也找出来了,依次循环,完成排序。
package com.wuxudong.sort;
import java.util.Arrays;
//堆排序
public class HeapSort {
public static void main(String[] args) {
int [] arr=new int []{9,6,8,7,0,1,10,4,2};
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void heapSort(int [] arr){
//开始的位置是最后一个非叶子节点,即最后一个节点的父节点
int start=(arr.length-1)/2;
//调整大顶堆
for (int i=start;i>=0;i--){
maxHeap(arr,arr.length,i);
}
//先把数组中的第0个和堆中的最后一个数交换位置,再把前面的处理为大顶堆
for (int i = arr.length-1; i>0 ; i--) {
int temp=arr[0];
arr[0]=arr[i];
arr[i]=temp;
maxHeap(arr,i,0);
}
}
//将数组转为大顶堆
public static void maxHeap(int [] arr,int size,int index){
//左节点
int leftNode=2*index+1;
//右节点
int rightNode=2*index+2;
//定义最大的节点
int max=index;
if(leftNode<size&&arr[leftNode]>arr[max]){
max=leftNode;
}
if (rightNode<size&&arr[rightNode]>arr[max]){
max=rightNode;
}
//交换位置
if(max!=index){
int temp=arr[index];
arr[index]=arr[max];
arr[max]=temp;
//交换位置后,可能会破坏之前排好的堆,所以,之前排好的堆需要重新调整
maxHeap(arr,size,max);
}
}
}