冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序、基数排序图解分析和代码演示

排序算法

1、内部排序:指将需要处理的的所有数据都需要加载到内部存储中进行排序

2、外部排序:数据量过大,无法将全部加载到内存中,需要借助外部存储进行排序

冒泡排序

介绍

通过从前往后遍历序列,依次比较相邻元素的值,将值较大的逐渐移动到最后

  • 一共进行数组大小-1循环
  • 每一趟排序的次数都在减少
  • 优化,在某一次排序中没有发生一次交换,就可以提前结束循环

图解

代码实现

/**
 * 冒泡排序
 */
public class BobbleSort {
    public static void main(String[] args) {
        int arr[] = {3,9,-1,10,20};

        int temp = 0;//用于交换数据的辅助变量
        for(int i = 0; i < arr.length-1; i++){

            for(int j = 0; j < arr.length-1-i;j++){//每一趟排序最大都会排在最后一位
                //arr.length-1原因arr[j+1]已经指向最后一位元素,如果是arr.length则出界
                if(arr[j]>arr[j+1]){
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

}

发现当进行到第三趟时,数据已经不进行交换,其实排序已经完成,所以为了优化程序,减少程序执行时间,可以定义一个boolean变量用来标记当一趟数据不发生交换时,直接跳出循环,输出排序后的结果,代码优化如下:

public class BobbleSort {
    public static void main(String[] args) {
//        int arr[] = {4,1,3,2};

        int [] arr = new int[80000];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random()*800000);
        }
        Date data1 = new Date();
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format1 = simpleDateFormat1.format(data1);
        System.out.println("排序前的时间:"+format1);

        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++){//每一趟排序最大都会排在最后一位
                //arr.length-1原因arr[j+1]已经指向最后一位元素,如果是arr.length则出界
                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;//重置
            }
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        Date data2 = new Date();
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format2 = simpleDateFormat2.format(data2);
        System.out.println("排序后的时间:"+format2);
    }

}

选择排序

基本介绍

第一次从数组中选择出一个最小的数,然后与数组第一个位置交换数据;第二次从数组的第二个位置选出一个最小的数,与数组第二个位置交换数据,直到排序完成

代码实现

public class SelectSort {
    public static void main(String[] args) {
        int[] arr = {4,2,6,3,7,5};
        selectSort(arr);

    }
    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[minIndex] = arr[i];
                arr[i] = min;
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

插入排序

基本介绍

把n个待排序的元素看成一个有序表和一个无序表,开始有序表只有一个元素,无序表中有n-1个元素,排序过程中每次从无序表中取出第一个元素,把他的排序码一次与有序表元素的排序码进行比较,将他插入有序表中适当位置,使之成为新的有序表

图解

代码实现

public class InsertSort {
    public static void main(String[] args) {
        int[] arr = {56,23,11,45,87};
        insertSort(arr);
    }
    public static void insertSort(int[] arr){

        for (int i = 1; i < arr.length; i++) {
            int insertValue = arr[i];
            int insertIndex = i-1;

            while (insertIndex>=0 && insertValue<arr[insertIndex]){
                arr[insertIndex+1] = arr[insertIndex];//往后移位置,直到找到要插入的位置之后都要移位置
                insertIndex--;//在已经排好顺序的前边,寻找
            }

            //退出while循环时,已经找到insertValue要插入的位置,insertIndex+1

            //判断是否赋值,要插入的位置刚好是排序完部分的最后一个元素的位置后一个,说明不用赋值
            if(insertIndex+1!=i){

                arr[insertIndex+1] = insertValue;
            }
        }


        System.out.println(Arrays.toString(arr));
    }
}

希尔排序

基本介绍

希尔排序是希尔在1959年提出的一种排序算法,也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序

图解

交换法

public class ShellSort {
    public static void main(String[] args) {

        int[] arr = {8,3,5,9,4,6,7,2};
        int n = arr.length;
        shellSort(arr);
    }
    public static void shellSort(int[] arr){

        int temp = 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;
                    }
                }
            }
        }

        System.out.println(Arrays.toString(arr));
    }
}

效率不高,发现一个就去交换,速度不是很快

移位法

 public static void shellSort(int[] arr){

        int temp = 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;
                    }
                }
            }
        }

        System.out.println(Arrays.toString(arr));
    }

快速排序

基本介绍

快速排序是对冒泡排序的一种改进,基本思想是通过一趟排序将要排序的数据分隔成独立的两部分,其中一部分的所有数据都比另外一部分数据都要小,然后再按此方法对这两部分进行快速排序,整个过程可以递归 进行,一次达到整个数据变成有序序列

图解

代码实现

public class QuickSort {
    public static void main(String[] args) {
        int [] arr = {2,1,0,-6,5,7};
        quickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));

    }
    public static void quickSort(int[] arr, int left, int right){
        int l = left;
        int r = right;
        int temp = 0;//辅助变量用于交换数据
        int pivot = arr[(left+right)/2];
        while(l<r){

            while(arr[l]<pivot){
                l += 1;
            }
            //找到比pivot大的数据下标

            while (arr[r]>pivot){
                r -= 1;
            }
            //找到比pivot小的数据下标

            if(l>=r){
                break;
            }
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            //发现交换完的数据和pivot相等,右指针左移
            if(arr[l]==pivot){
                r -= 1;
            }

            if(arr[r]==pivot){
                l += 1;
            }
        }
        //如果l==r,必须l++,r--,否则会溢出
        if(l==r){
            l += 1;
            r -= 1;
        }
        //向左递归
        if(left<r){
            quickSort(arr,left,r);
        }
        //向右递归
        if(right>l){
            quickSort(arr,l,right);
        }
    }
}

归并排序

基本介绍

归并排序是利用归并的 思想实现的排序方法,该算法采用的分治策略,将问题分成一些小问题然后递归求解,而治的夹断就将分的阶段得到的个答案合并在一起

图解

代码实现

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {8,4,5,7,1,3,6,2};
        int temp[] = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 分和合方法
     * @param arr
     * @param left
     * @param right
     * @param temp
     */
    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);
            //合并
            mergeSort(arr,left,mid,right,temp);

        }
    }
    /**
     * 合并方法
     * @param arr   排序的数据
     * @param left  左边有序列的初始序列
     * @param mid   中间索引
     * @param right 右边索引
     * @param temp  做中转的数组
     */
    public static void mergeSort(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 += 1;
                i += 1;
            }else {
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }
        //将一边序列的剩余数据全部填充到数组中
        while (i<=mid){//左边序列剩余数据
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }
        while (j<=right){//右边序列会剩余数据
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }

        //将所有数据拷贝到arr中,但是并不是每一次都要全部拷贝
        t = 0;
        int tempLeft = left;
        System.out.printf("tempLeft=%d right=%d\n",tempLeft,right);
        while(tempLeft<=right){//第一次合并tempLeft=0 right=1 第二次合并tempLeft=1 right=2 第三次合并tempLeft=0 right=3...
            // 直到最后一次才是tempLeft=0 right=7
            arr[tempLeft] = temp[t];
            t += 1;
            tempLeft +=1;
        }
    }
}

基数排序

基本介绍

基数排序属于“分配式排序”,又称“桶子法”,它是通过键值的各个位的值,将要排序的元素分配在某些桶中,达到排序的作用

思路分析

将每个元素的个位数取出,然后看这个数在哪个对应的桶中

代码实现

package com.bai.sort;

import java.util.Arrays;

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){
        //定义一个二维数组,表示十个桶,每一个桶就是一个数组
        //为了防止溢出,将每一个数组的大小都设为arr.length
        //所以基数排序是以空间换时间的经典算法
        int[][] bucket = new int[10][arr.length];

        //记录每个桶中存入数据的个数,bucketElementsCounts[0]表示bucket[0]的数据个数
        int[] bucketElementsCounts = new int[10];

        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i]>max){
                max = arr[i];
            }
        }
        int maxLength = (max+"").length();

        for (int s = 0, n = 1;s<maxLength;s++, n *= 10){
            for (int i = 0; i < arr.length; i++) {
                int digitOfElement = arr[i]/n%10;
                bucket[digitOfElement][bucketElementsCounts[digitOfElement]] = arr[i];
                bucketElementsCounts[digitOfElement]++;
            }
            int index = 0;
            //遍历每一个桶
            for (int j = 0; j < bucket.length; j++){
                if(bucketElementsCounts[j] != 0){
                    for (int k = 0;k<bucketElementsCounts[j];k++){
                        arr[index++] = bucket[j][k];
                    }
                }
                //每趟排序完都得至0,下一个存入
                bucketElementsCounts[j] = 0;
            }
            System.out.println(Arrays.toString(arr));
        }

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值