一、冒泡排序

1、定义:比较相邻的元素。从最后一个数跟倒数倒二个数两两比较,大的往后排。

2、代码

import java.util.Arrays;

public class BubbleTest {
    public static void main(String[] args){
        int[] a=new int[]{6,9,1,4,5,8,7,0,2,3};
        System.out.println("排序前: " + Arrays.toString(a));
        BubbleSort(a);
        System.out.println("排序后: " + Arrays.toString(a));
    }
    
    
    public static void BubbleSort(int[] arr){
        
        int len = arr.length;
        
        //外循环表示趟数
        for(int i = 0; i < len; i++){
            boolean flag = false;
            
            //内循环进行排序比较
            for(int j = len-1; j > i; j--){
                if(arr[j-1] > arr[j]){
                    int temp = arr[j-1];
                    arr[j-1] = arr[j];
                    arr[j] = temp;
                    flag = true;
                }
            }
            // 如果没有发生交换,则已经有序,结束冒泡
            if(flag == false){
                return;
            }
            System.out.println("第"+ i +"趟: " + Arrays.toString(arr));
        }    
    
    }
}

二、选择排序

1、定义:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止

2、流程

  (1)从待排序序列中,找到关键字最小的元素;

  (2)如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;

   (3)从余下的 N - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束。

  

3、代码

import java.util.Arrays;

public class ChooseTest {
    public static void main(String[] args){
        int[] a=new int[]{6,9,1,4,5,8,7,0,2,3};
        System.out.println("排序前: " + Arrays.toString(a));
        ChooseSort(a);
        System.out.println("排序后: " + Arrays.toString(a));
    }
    
    
    public static void ChooseSort(int[] arr){
        
        int len = arr.length;
        
        //遍历获取最小值
        //要排序N个数,当排到N-1遍遍历之后,已经是有序
        for(int i = 0; i < len-1; i++){
            
            int temp = 0;
            int index = i;//用来存放最小值的索引
            
            //内循环进行排序比较
            for(int j = i+1; j <len; j++){
                if(arr[index] > arr[j]){
                    index = j;
                }
            }
            
            // 将找到的第i个最小值放在i位
            temp = arr[index];
            arr[index] = arr[i];
            arr[i] = temp;
            
            System.out.println("第"+ i +"趟: " + Arrays.toString(arr));
        }    
    
    }
}

 三、快速排序

1、定义:通过一趟排序将要排序的数据分割成独立的两部分:分割点左边都是比它小的数,右边都是比它大的数。然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

 例如:

分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端开始“探测”。先从找一个小于6的数,再从找一个大于6的数,然后交换他们。这里可以用两个变量i和j,分别指向序列最左边和最右边。

 

 哨兵j一步一步地向左挪动(即j–),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。然后交换哨兵i和哨兵j所指向的元素的值。

 

 

 

 

第一次交换结束,接下来开始哨兵j继续向左挪动,发现了4(比基准数6要小,满足要求)之后停了下来。哨兵i也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。此时再次进行交换。

 

 

 第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。

 

 

 到此第一轮“探测”真正结束。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。

 

现在基准数6已经归位,它正好处在序列的第6位。此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是“3 1 2 5 4”,右边的序列是“9 7 10 8”。接下来分别用场面的方面处理6左边序列和右边序列。左边的序列是“3 1 2 5 4”。请将这个序列以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。

 

import java.util.Arrays;

public class FastSort{

     public static void main(String []args){
       
        int[] a = {10,7,2,4,7,62,3,4,2,1,8,9,19};
        int start = 0;
        int end = a.length-1;
         
        System.out.println("排序前: " + Arrays.toString(a)); 
        sort(a,start,end);
        System.out.println("排序后: " + Arrays.toString(a));
        
     }
     
     public static void sort(int[] a,int low,int high){
        
         int start = low;
         int end = high;
         int key = a[low];
         
         while(end>start){
             //从后往前比较
             while(end>start&&a[end]>=key)//如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                 end--;
             if(a[end]<=key){
                 int temp = a[end];
                 a[end] = a[start];
                 a[start] = temp;
             }
             //从前往后比较
             while(end>start&&a[start]<=key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                start++;
             if(a[start]>=key){
                 int temp = a[start];
                 a[start] = a[end];
                 a[end] = temp;
             }
         //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
         }
         //递归
         if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
         if(end<high) sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
     }
     
}

 

 四、直接插入排序

1、定义:每一趟将一个待排序的记录,按照其关键字的大小插入到有序队列的合适位置里,知道全部插入完成。

2、代码

例子一:

import java.util.Random;

public class InsertSort {
    public void insertSort(int[] list) {

        // 打印第一个元素
        System.out.format("i = %d:\t", 0);
        printPart(list, 0, 0);

        // 第1个数肯定是有序的,从第2个数开始遍历,依次插入有序序列
        for (int i = 1; i < list.length; i++) {
            
            int j = 0;
            int temp = list[i]; // 取出第i个数,和前i-1个数比较后,插入合适位置

            // 因为前i-1个数都是从小到大的有序序列,所以只要当前比较的数(list[j])比temp大,就把这个数后移一位

            for (j = i - 1; j >= 0 && temp < list[j]; j--) {

                list[j + 1] = list[j];

            }

            list[j + 1] = temp;

            System.out.format("i = %d:\t", i);

            printPart(list, 0, i);

        }

    }


    // 打印序列

    public void printPart(int[] list, int begin, int end) {

        for (int i = 0; i < begin; i++) {

            System.out.print("\t");

        }

        for (int i = begin; i <= end; i++) {

            System.out.print(list[i] + "\t");

        }

        System.out.println();

    }


    public static void main(String[] args) {

        // 初始化一个随机序列

        /**final int MAX_SIZE = 10;

        int[] array = new int[MAX_SIZE];

        Random random = new Random();

        for (int i = 0; i < MAX_SIZE; i++) {

            array[i] = random.nextInt(MAX_SIZE);

        }*/


        int[] array=new int[]{6,9,1,4,5,8,7,0,2,3};
        
        // 调用插入排序方法
        InsertSort insert = new InsertSort();

        System.out.print("排序前:\t");

        insert.printPart(array, 0, array.length - 1);

        insert.insertSort(array);

        System.out.print("排序后:\t");

        insert.printPart(array, 0, array.length - 1);

    }

}

例子2:

import java.lang.reflect.Array;
import java.util.Arrays;

public class Solution {
    public static void main(String[] args) {
        int[] a=new int[]{6,9,1,4,5,8,7,0,2,3};
        System.out.println("排序前: " + Arrays.toString(a));
        InsertSort(a);
        System.out.println("排序前: " + Arrays.toString(a));
    }
    public static void InsertSort(int [] arr){
        int value;//待插入元素
        int index;//初始值为待插入元素前一个元素的索引

        //i从第二个元素开始,默认第一个元素是有序的
        for(int i= 1 ; i< arr.length;i++){
            
            value = arr[i];
            index = i - 1;//初始为前一个元素
            
            while(index >=0 && value < arr[index]){
                //需要保证index合法
                //每当前面的元素比待插入元素大,就向后移动
                arr[index + 1] = arr[index];
                //不用怕覆盖,因为value保存着待插入的值
                index--;
            }
            //当退出循环,表明已经找到了待插入位置,即index + 1
            arr[index + 1] = value;
            System.out.println("第"+i+"次排序: "+Arrays.toString(arr));
        }
        
    }
}

 五、希尔排序

1、定义:又称为缩小增量排序,它是一种插入排序。即把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。希尔排序的一个特点是:子序列的构成不是简单的“逐段分割”,而是将相隔某个“增量”的记录组成一个子序列。

 

 

 2、流程

(1)在第一趟排序中,我们不妨设 gap1 = N / 2 ,然后分为段排序;

(2)我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2(取整);

(3)在第三趟排序中,再次把 gap 缩小一半,即gap3 = gap2 / 2。

3、代码:、

import java.util.Arrays;

public class ShellTest {
    public static void main(String[] args){
        int[] a = {5,2,4,1,3,9,8,6,7,0};
        System.out.println("排序前: " + Arrays.toString(a));
        ShellSort(a);
        System.out.println("排序后: " + Arrays.toString(a));
    }
    
    
    public static void ShellSort(int[] arr){
        
        //只有一个元素或者元素为空时,直接返回数组
        /**if(arr.length<2){
            return arr;
        }*/
        
        // 获得每次分组的步长
        int len = arr.length/2;
        while(len >= 1){
            for(int i = len; i < arr.length; i++){

                int shellcCode = arr[i];
                int j = i-len;

                while(j >= 0 && shellcCode < arr[j]){
                    arr[j+len] = arr[j];
                    j -= len;
                }
                arr[j+len] = shellcCode;
            }        
 
            System.out.println("gap = "+len+":"+ Arrays.toString(arr));
            len = len/2;
            
        }   
        //return arr;
    }
    
}

 

六、二分插入排序(又称折半插入排序)

  直接插入需要将有序数据一个个进行查找,效率较慢,二分插入的中心思想就是使用二分查找法在有序区间进行查找,减少查找量。

import java.util.Arrays;

class Untitled {
    public static void main(String[] args) {
        //定义一个长度为10的数组
        int[] arr = { 1, 3, 4, 2, 6, 7, 8, 0, 5 };
        System.out.println("排序前:" + Arrays.toString(arr));
        
        long startTime = System.nanoTime(); // 获取排序开始时间
        
        for(int i=1;i<=arr.length-1;i++) {
            if(arr[i]<arr[i-1]) {
                
                int low=0;
                int hight=i-1;
                int temp=arr[i];  
                
                while(low<=hight) {
                    
                    int mid=(low+hight)/2;
                    
                    if(temp<arr[mid]) {
                        
                        hight=mid-1;
                        
                    }else {
                        
                        low=mid+1;
                        
                    }
                }
                
                for(int j=i-1;j>=low;j--) {
                    
                    arr[j+1]=arr[j];
                    
                }
                
                arr[low]=temp;
            }
        }
        
          long endTime = System.nanoTime(); // 获取排序结束时间
          System.out.println("排序結果:" + Arrays.toString(arr));
          System.out.println("程序运行时间: " + (endTime - startTime) + "ns");
    }
}

 

posted on 2020-05-12 21:58  小潘同学  阅读(225)  评论(0)    收藏  举报
-->