Java数据结构7:排序算法

第7章:排序算法

1、排序

内部排序:

将需要处理的所有数据都加载到内存中进行排序。

外部排序:

数据量过大,无法全部加载到内存中,需要借助外部存储(文件等)进行排序

image-20201107194334400

时间频度:

一个算法中语句执行次数

时间复杂度:

算法中的基本操作语句的重复执行次数是问题规模n的某个函数。

空间复杂度:

临时占用存储空间大小的度量

常见的算法时间复杂度由小到大依次为:
O ( 1 ) < O ( l o g 2 n ) < O ( n ) < O ( n l o g 2 n ) < O ( n 2 ) < O ( n 3 ) < O ( n k ) < O ( 2 n ) Ο(1)<Ο(log_2n)<Ο(n)<Ο(nlog_2n)<Ο(n^2)<Ο(n^3)< Ο(n^k) <Ο(2^n) O(1)O(log2n)O(n)O(nlog2n)O(n2)O(n3)O(nk)O(2n)

  1. 常数阶O(1)
int i=1;
int j=2;
++i;
j++;
int m=i+j;
  1. 对数阶
    O ( l o g 2 n ) O(log_2n) O(log2n)

    int i = 1;
    while (i < n) {
        i = i * 2;
    }
    
  2. 线性阶O(n)

for (i = 1; i <= n; ++i) {
    j = i;
    j++;
}
  1. 线性对称阶
    O ( n l o g 2 N ) O(nlog_2N) O(nlog2N)

    for (m = 1; m < n; m++) {
        i = 1;
        while (i < n) {
            i = i * 2;
        }
    }
    
  2. 平方阶
    O ( n 2 ) O(n^2) O(n2)

for (x = 0; i <= n; x++) {
    for (i = 1; i <= n; i++) {
        j = i;
        j++;
    }
}

image-20201107200857546

2、冒泡排序

依次比较相邻元素的值,若发现逆序则交换。
O ( n 2 ) O(n^2) O(n2)
image-20201107202237348

  1. 一共进行n-1次大循环
  2. 每一趟排序次数都在减少
  3. 某趟排序中没有发生一次交换,可以提前结束冒泡排序
//冒泡排序
public static void bubbleSort(int[] arr){
    boolean flag=false;
    int temp=0;
    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;
                temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
        if (!flag){//这一趟没有发生交换
            break;
        }else{
            flag=false;
        }
    }
}

3、选择排序

第一次从arr[0]-arr[n-1]中选取最小值与arr[0]交换,依次循环,n-1次
O ( n 2 ) O(n^2) O(n2)
image-20201107203109384

image-20210307172237775

public static void selectSort(int[] arr){

        for (int i = 0; i <arr.length-1 ; i++) {
             int minIndex=i;    //最小值下标
             int min=arr[i];    //假设最小值
            for (int j = i+1; j < arr.length; j++) {
                if (min>arr[j]){    //假设的不是最小值
                    min=arr[j];     //重置最小值和下标
                    minIndex=j;
                }
            }
            if (minIndex!=i){
                arr[minIndex]=arr[i];   //交换
                arr[i]=min;
            }

        }
    }

4、插入排序

把第一个元素看成是有序表,依次从无序表中取出与有序表进行比较插入。

image-20201107204211958

public static void insertSort(int[] arr){
    int val=0;//插入的值
    int index=0;
    for (int i = 1; i < arr.length; i++) {
        val=arr[i];
        index=i-1;    //有序列表最后一个数

        while (index>=0&&val<arr[index]){ //从有序列表最后一个数开始找插入位置
            arr[index+1]=arr[index];       //后移
            index--;
        }
        if (index+1!=i){
            arr[index+1]=val;
        }
    }
}

5、希尔排序:高效的插入排序

把元素按增量进行(length/2)分组,对每组使用直接插入排序算法;

随着增量(length/2)逐渐减少,每组包含的关键词越来越多,当增量减至1时,所有元素分成一组。

image-20201107204840326

image-20201107204859380

public static void shellSort(int[] arr){
    int temp=0;
    int count=0;
    for (int gap = arr.length/2; gap >0 ; gap/=2) {
        
        for (int i = gap; i <arr.length ; i++) {
            
            for (int j=i-gap;j>=0;j-=gap){
                
                if (arr[j]>arr[j+gap]){
                    
                    temp=arr[j];
                    arr[j]=arr[j+gap];
                    arr[j+gap]=temp;
                }
            }
        }
    }
}

6、快速排序-递归

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,递归进行。

image-20201107205033164

image-20201107205110737

public static void quicksort(int[] arr, int start, int end) {
    int i = start;
    int j = end;
    int pivot = arr[(start + end) / 2];//取中间的数为基准
    int temp = 0;
    while (i < j) {
        while (arr[i] < pivot) {
            i++;
        }
        while (arr[j] > pivot) {
            j--;
        }
        if (i >= j) {
            break;
        }
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;

        if (arr[i] == pivot) {
            j--;
        }
        if (arr[j] == pivot) {
            i++;
        }
        if (i == j) {
            i++;
            j--;
        }
        if (start < j) {
            quicksort(arr, start, j);
        }
        if (end > i) {
            quicksort(arr, i, end);
        }
    }
}

7、归并排序

分治策略

image-20201107210829443

将两个有序[4,5,7,8]和[1,2,3,6]合并为一个有序

image-20201107210901372

public class MergeSort {
    public static void main(String[] args) {
        int[] arr={8,9,1,7,2,3,5,4,6,0};
        int[] temp=new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println(Arrays.toString(arr));
    }
	//分解
    public static void mergeSort(int[] arr,int left,int right,int[] temp){
        if (left<right){
            int mid=(left+right)/2;

            mergeSort(arr,left,mid,temp);

            mergeSort(arr,mid+1,right,temp);

            merge(arr,left,mid,right,temp);//合并
        }
    }

    //合并
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i=left;     //左边初始索引
        int j=mid+1;    //右边初始索引
        int t=0;        //temp当前索引
        while (i<=mid&&j<=right){
            if (arr[i]<=arr[j]){
                temp[t]=arr[i];
                t++;
                i++;
            }else {
                temp[t]=arr[j];
                t++;
                j++;
            }
            while (i<=mid){     //左边剩余
                temp[t]=arr[i];
                t++;
                i++;
            }
            while (j<=right){   //右边剩余
                temp[t]=arr[j];
                t++;
                j++;
            }
            //把temp数组中的元素拷贝到arr
            t=0;
            int tempLeft=left;
            while(tempLeft<=right){
                arr[tempLeft]=temp[t];
                t++;
                tempLeft++;
            }
        }
    }
}

8、基数排序(桶排序)

桶排序:空间换时间
基本思想:将所有待比较数值统一为同样数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成。

image-20201107211338616

  1. 对桶排序的扩展
  2. 以空间换时间
  3. 稳定
  4. 如有负数,不使用基数排序
public class RadixSort {
    public static void main(String[] args){
        int[] arr={53,3,542,748,14,214};
        radixSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void radixSort(int[] arr){
        int max=arr[0];     //获取最大值
        for (int i = 0; i < arr.length; i++) {
            if(arr[i]>max){
                max=arr[i];
            }
        }
        int maxLength=(max+"").length();    //最大值的位数

        int[][] bucket=new int[10][arr.length];     //10个桶,最多全部数据在一个桶

        int[] counts=new int[10];       //counts[0]表示第一个桶有多少个数


        for (int i = 0,n=1; i <maxLength; i++,n*=10) {      //个位十位百位
            for (int j = 0; j < arr.length; j++) {
                int digEl=arr[j]/n%10;
                bucket[digEl][counts[digEl]]=arr[j];
                counts[digEl]++;
            }

            int index=0;
            for(int k=0;k<counts.length;k++){
                if (counts[k]!=0){      //k桶数据
                    for (int j = 0; j < counts[k]; j++) {
                        arr[index++]=bucket[k][j];      //拷贝到数组中
                    }
                }
                counts[k]=0;
            }
        }
    }
}

总结

image-20201107211438030

image-20201107211444937

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值