前言
一个算法中语句执行的次数成为语句频度,记为T(n)。
想了解上面时间复杂度情况可看[时间复杂度举例](https://blog.csdn.net/qq_17534301/article/details/82872357
稳定性:任意两个相等的数据,排序后相对位置不变。
八大排序算法
1.冒泡排序
①思想:冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。图解如下
②代码实现
public class BubbleSort {
public static void main(String[] args) {
int[] a = { 4, 5, 1, 7, 0, 9, 6, 3, 2, 8 };
bubbleSort(a);
}
public static void bubbleSort(int[] arr) {//传入数组
for (int i = 1; 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;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
//优化后的代码
public class BubbleSort {
public static void main(String[] args) {
int[] a = { 3,9,-1,10,20 };
bubbleSort(a);
}
public static void bubbleSort(int[] arr) {//传入数组
boolean flag =false;
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]) {
flag=true;
int temp; //用临时变量交换
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第"+(i+1)+"趟交换");
System.out.println(Arrays.toString(arr));
if(!flag){//如果在一次循环中没有交换,break
break;
}else{ //如果进入程序进行交换,重置flag
flag=false;
}
}
}
}
2.快速排序
①思想:、先从数列中取出一个数作为基准数分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边,再对左右区间重复第二步,直到各区间只有一个数。
②图解与代码实现
第一次以0为基准
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int arr [] ={2,1,3,4,0,7,5,9,4,10,-1};
quicksort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void quicksort(int arr[] ,int start ,int end){
if(start<end){
int stand=arr[start];//将数组第一个数字当作基准数
int left = start;//记录下需要排序的下标
int right= end;
while(left<right){//循坏比标准数大的数,比标准数小的数
while(left<right&&stand<=arr[right]){ //右边数字比标准数大,下标移动
right--;
}
arr[left]=arr[right];
while(left<right&&arr[left]<stand){
left++;
}
arr[right]=arr[left];
}
arr[left]=stand;
quicksort(arr,start ,left);
quicksort(arr,left+1 ,end);
}
}
}
3.插入排序
①思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序
②代码实现:
public class InsertSort {
public static void main(String[] args) {
int[] arr = new int[]{5, 3, 2, 8, 5, 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&& arr[j]>temp ; j--) {
//把前一个数字赋值给后一个
arr[j+1]=arr[j];
}
//把临时变量(外层for循坏的当前元素)赋值给不满足条件的后一个元素
arr[j+1]=temp;
}
}
}
}
4.希尔排序
其工作原理是定义一个步长来表示排序过程中进行比较的元素之间有多远的间隔,每次将具有相同间隔的数分为一组,进行插入排序。希尔排序的实质就是分组的插入排序
https://blog.csdn.net/qq_37466121/article/details/85957138
5.选择排序
https://blog.csdn.net/weixin_42312342/article/details/89305495
①工作原理是:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
每次我只要最小的
②代码实现
public class SelectSort {
public static void main(String[] args) {
int [] arr = new int[]{3,5,1,2,0,6,9,8,4};
selectSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void selectSort(int [] arr){
for (int i = 0; i <arr.length ; i++) {
int mixIndex=i;//把当前遍历的数字和后面所有数字进行比较并记录下最小的数字下标
for (int j = i+1; j <arr.length; j++) {
if(arr[mixIndex]>arr[j]) {//如果后面记录的数字比记录的最小的还小
mixIndex=j;
}
}//如果最小的数字和当前遍历数的下标不一致,说明下标minindex的数比当前遍历的数更小
if(i!=mixIndex){
int temp =arr[i];
arr[i]=arr[mixIndex];
arr[mixIndex]=temp;
}
}
}
}
6.归并排序
①Step1:先依次划分下去,如图中例子分三次
https://blog.csdn.net/k_koris/article/details/80508543
分到一定细度的时候,每一个部分就只有一个元素了,那么我们此时不用排序,对他们进行一次简单的归并就好了。
Step2,从下(小的组)到上进行回归归并
②代码实现
public class MergeSort {
public static void main(String[] args) {
int [] arr =new int[]{1,2,1,4,3,9};
mergeSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public 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);
}
}
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++;
}
//因为如果当某一边数组没有数字,就无法进入while循坏,所以将另一边剩的数据也要存入,如123 4536
while (j<=high){
temp[index]=arr[j];
j++;
index++;
}
while (i<=middle){
temp[index]=arr[i];
i++;
index++;
}
for (int k = 0; k <temp.length ; k++) {
arr[k+low]=temp[k];
}
}
}