数据结构—排序问题:冒泡、选择、插入、归并、快排、计数、基数(桶)

缺失:希尔排序、堆排序
优化:快速排序

待补充状态

导读
 简单算法:冒泡排序O(n2)、简单选择排序O(n2)、直接插入排序O(n2)
 改进算法:归并排序O(nlogn)、快速排序(冒泡排序优化)O(nlogn)、计数排序、基数排序或桶子法、希尔排序(插入排序优化)O(n3/2)、堆排序(选择排序优化)O(nlogn)

1. 排序问题

1.0 直接使用Arrays.sort(数组名)方法进行排序

  int[] d={123,456,19};
  Arrays.sort(d);

但有时需要我们使用算法实现,则基本排序常用方法如下:

    public static void main(String[] args) {
        int[] num = {230,229,8,0,26,25,224,223};
        bubbleSort(num);       //1.1 冒泡排序
        selectSort(num);       //1.2 选择排序
        insertSort(num);       //1.3 插入排序
        mergeSort(num);        //1.4 归并排序
        quickSort(num);        //1.5 快速排序
        Arrays.toString(num);  //打印数组
    }

1.1 冒泡排序:BubbleSort

冒泡排序主要是比较相邻的两位数字,取较大值与下一位比较,直至到最高位,完成一轮;第二轮比较至次高位,以此类推

    public static void bubbleSort(int[] num) {
        for (int i = num.length - 1,temp=0; i > 0; i--) {
            for (int j = 0; j < i; j++) {
                if (num[j] > num[j + 1]) {
                    temp = num[j];
                    num[j] = num[j + 1];
                    num[j + 1] = temp;
                }
            }
        }
    }  

1.2 选择排序:SelectSort

选择排序,首先选出最小值放在第一位;第二轮选出次小值放在第二位,以此类推

    public static void selectSort(int[]num) {
        for (int i = 0,temp=0; i < num.length-1; i++) {
            for(int j=i+1;jnum[j]){
                    temp = num[j];
                    num[j] = num[i];
                    num[i] = temp;
                }
            }
        }
    }

1.3 插入排序:InsertSort

先选定第二个数为标记数,当且仅当第一个数大于等于标记数时,才循环,交换标记数与第一个数的位置,此时设置第一个数为标记数;以此类推

    public static void insertSort(int[]num) {
        for (int i = 1,temp=0,j=0; i < num.length; i++) {
            temp=num[i];
            j=i;
            while(j>0&&num[j-1]>temp){
                num[j]=num[j-1];
                num[j-1]=temp;
                j--;
            }
        }
    }

1.4 归并排序:MergeSort

分治策略;序列一分为二,然后对子序列进行递归排序,最后合并有序子序列

    public static void mergeSort(int[]num){
            sort(num,0,num.length-1);
    }
    public static void sort(int[]num,int left,int right){
        if(left>1;
             sort(num,left,center);
             sort(num,center+1,right);
             merge(num,left,center,right);
        }        
    }
    public static void merge(int[]num,int left,int center,int right){
             //创建临时数组,暂存数据
        int[] tmpArr=new int[num.length];
        int third=left;
        int temp=left;
        int mid=center+1;
            //对两个子序列中取出较小的放入临时数组,直至某子序列全部放完 
        while(left<=center&&mid<=right){            
            if(num[left]<=num[mid]){
                tmpArr[third++]=num[left++]; 
            }else{
                tmpArr[third++]=num[mid++]; 
            }
        }
              //此处两个while只能运行一个
        while(mid<=right){
            tmpArr[third++]=num[mid++];
        }
        while(left<=center){
            tmpArr[third++]=num[left++];
        }
               //此处把数据从临时数组中复制回原数组
         while(temp<=right){
            num[temp]=tmpArr[temp++];
        }
    }
      

1.5 快速排序

以数组中的某位随机数为比较值key,从右、左分别向中间逼近,一次排序把小于比较值key的放在左边,大于比较值key的放在右边,然后再对两边子序列分别进行排序,以此类推

1.5.1 基本快速排序:QuickSort

以数组中的首数或尾数为比较值key:

    public static void quickSort(int[]num){
        if(num==null||num.length<=0){
            System.out.println("error data");
            return;
        }
        sort(num,0,num.length-1);
    }
    public static void sort(int[] num,int left,int right){
        if(left
1.5.2 随机化快速排序:RandomQuickSort

随机设定比较值key:

    public static void randomQuickSort(int[] num) {
        if (num == null || num.length <= 0) {
            System.out.println("error data");
            return;
        }
        sort(num, 0, num.length - 1);
    }
    public static void sort(int[] num, int left, int right) {
        if (left < right) {
            int middle = randomNum(num, left, right); //内容有变动
            sort(num, left, middle - 1);
            sort(num, middle + 1, right);
        }
    }
         //新增方法
    public static int randomNum(int[] num, int left, int right) {
        //获取left与right中间的任意随机值
        int random = (int) (left + Math.random() * (right - left)); 
        int temp = num[left];
        num[left] = num[random];
        num[random] = temp;
        return getMiddle(num, left, right);
    }
    public static int getMiddle(int[] num, int left, int right) {
        int tmp = num[left];
        while (left < right) {
            while (left < right && tmp <= num[right]) {
                right--;
            }
            if (left < right) {
                num[left] = num[right];
                left++;
            }
            while (left < right && num[left] <= tmp) {
                left++;
            }
            if (left < right) {
                num[right] = num[left];
                right--;
            }
        }
        num[left] = tmp;
        return left;
    }

1.6 计数排序:CountSort

统计数组中的各数出现的次数,然后再安排先后顺序一一打印出来

    public static void countSort(int[] num) {
        if(num==null||num.length<=0){
            System.out.println("error data");
            return;
        }
        int max=0,min=0;
        for(int i=0;i<=num.length-1;i++){
            if(num[i]max){
                max=num[i];
            }
        }
        int [] newNum=new int[max-min+1];
        for(int i=0;i<=num.length-1;i++){
            newNum[num[i]-min]++;
        }
        int count=0;
        for(int i=0;i0){
                num[count++]=min+i;
                newNum[i]--;
            }
        }
    }

1.7 基数排序或桶子法:RadixSort 或 BucketSort

1.7.1 LSD法

最低位优先(Least Significant Digit first)法:先获取最高位数,然后从低向高依次排序,即个、十、百、千位···

    import java.util.List;           //导入List集合包
    import java.util.ArrayList;      //导入ArrayList包
   public static void radixSort(int[] num) {
        if (num == null || num.length <= 0) {
            System.out.println("error data");
            return;
        }
        sort(num);
    }

    public static void sort(int[] num) {
        // 计算数组中最大数k的位数time
        int k = num[0], time = 1;
        for (int i = 0; i < num.length; i++) {
            k = k < num[i] ? num[i] : k;
        }
        while (k / 10 != 0) {
            time++;
            k /= 10;
        }
        // 创建0-9个ArrayList存放数据
        List queue = new ArrayList();
        for (int i = 0; i < 10; i++) {
            ArrayList queue1 = new ArrayList();
            queue.add(queue1);
        }
        // 进行time次分配
        for (int i = 0; i < time; i++) {
            for (int j = 0; j < num.length; j++) {
                int x = num[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                ArrayList queue2 = queue.get(x);
                queue2.add(num[j]);
                queue.set(x, queue2);
            }
            // printqueue(queue); //打印list数组
            int count = 0;
            // 收集队列元素
            for (int m = 0; m < 10; m++) {
                for (int t = 0; t < queue.get(m).size(); t++) {
                    num[count++] = (int) queue.get(m).get(t);
                }
                queue.get(m).clear();
            }
        }
    }
1.7.2 MSD法

最高位优先(Most Significant Digit first)法:先获取最高位数,然后依次从高位到低位进行排序;即···千、百、十、个位

暂时缺失


## 排序的稳定性与不变性
#### 不变性
在算法运行时保持不变的条件
#### 稳定性
如果具有相同关键字的数据项,经过排序它们的顺序保持不变,这样的排序就是稳定的

你可能感兴趣的:(数据结构—排序问题:冒泡、选择、插入、归并、快排、计数、基数(桶))