排序算法学习笔记

1.桶排序

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc:桶排序 条件:有个桶数组的下标都包含了需要排序的所有数据
 *       这样就把需要排序的数据一个个的放入对应的桶中
 *       再依次取出桶中有数据的数据  缺陷:不重复的小数据量
 * Date: Created in 18-9-1 下午5:44
 */
public class BucketSort {

    public static void main(String[] args){
        int[] DATA  ={8,2,1,5,9,7};
        // 构造桶: DATA值在0~9之间 所以桶的下标也是0~9
        int[] BUCKET = new int[10];
        // 初始化为空
        int Empty = -1;
        Arrays.fill(BUCKET,Empty);
        // 把数据放入桶中
        for (int i = 0; i < DATA.length; i++) {
            int value = DATA[i];
            BUCKET[value]=value;
        }
        // 再把桶中的数据依次取出来
        int j=0;
        int[] SortData = new int[DATA.length];
        for (int i = 0; i < BUCKET.length; i++) {
            if(BUCKET[i]!=Empty){
                SortData[j] = BUCKET[i];
                j++;
            }
        }
        System.out.println(Arrays.toString(SortData));

    }

}

2.基数排序

package com.xtm.main;

import java.util.Arrays;
import java.util.LinkedList;

/**
 * Author: TianMing.Xiong
 * Desc: 基数排序 实现:分别对数组中的元素的低位到高位进行桶排序,低位排序好的新数组再次进行高位桶排序,相同的数字添加到对应桶的链表中
 * Date: Created in 18-9-4 上午9:52
 */
public class RadixSort {
    public static void main(String[] args){
        // 待排序数组
        int[] DATA = {123,602,82,777,57,510,396,196,843,138};
        // 初始化桶数组 数字0~9标注桶的编号
        Object[] bucket = new Object[10];
        // 每个桶中装一个链表
        for (int i = 0; i < DATA.length; i++) {
            LinkedList<Integer> list = new LinkedList<>();
            bucket[i]= list;
        }
        // 1.根据个位上的数字装入桶中
        for (int i = 0; i < DATA.length; i++) {
            int digit = DATA[i] % 10;
            ((LinkedList<Integer>) bucket[digit]).add(DATA[i]);
        }

        // 取出根据个位排序好的新数组
        int[] newData1 = inputBucket(bucket, DATA);
        System.out.println(Arrays.toString(newData1));

        // 2.根据十位上的数字装入桶中
        for (int i = 0; i < DATA.length; i++) {
            int digit = newData1[i] % 100 / 10;
            ((LinkedList<Integer>) bucket[digit]).add(newData1[i]);
        }
        // 取出根据十位排序好的新数组
        int[] newData2 = inputBucket(bucket, DATA);
        System.out.println(Arrays.toString(newData2));

        // 3.根据百位上的数字装入桶中
        for (int i = 0; i < DATA.length; i++) {
            int digit = newData2[i] % 1000 / 100;
            ((LinkedList<Integer>) bucket[digit]).add(newData2[i]);
        }
        // 取出根据百位排序好的新数组
        int[] newData3 = inputBucket(bucket, DATA);
        System.out.println(Arrays.toString(newData3));


    }
    // 取出根据桶排序好的数据
    private static int[] inputBucket(Object[] bucket, int[] data) {
        int k = 0;
        int[] newData = new int[data.length];
        for (int i = 0; i < 10; i++) {
            LinkedList<Integer> linkedLists = (LinkedList<Integer>) bucket[i];
            for (Integer j:linkedLists){
                if(j!=0){
                    newData[k++] = j;
                }
            }
            linkedLists.clear();
        }
        return newData;
    }


}

3.选择排序

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc : 选择排序
 * Date: Created in 18-9-4 下午3:44
 */
public class SelectSort {
    public static void main(String[] args){
       int[] data = {35,80,21,54,11,45,92,39};
        for (int i = 0; i < data.length; i++) {
            int minIndex = i;// 保留本趟比较中最小值的索引
            for (int j = i+1; j <data.length ; j++) {
                if(data[j]<data[minIndex]){
                    minIndex = j;
                }
            }
            // 每趟比较最多交换一次
            if(i!=minIndex){
                int tmp = data[i];
                data[i] = data[minIndex];
                data[minIndex] = tmp;
            }
        }
        System.out.println(Arrays.toString(data));

    }
}

4.冒泡排序

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc: 冒泡排序
 * Date: Created in 18-9-4 下午5:07
 */
public class BubbleSort {
    public static void main(String[] args){
        int[] data ={19,80,77,11,54};
        for (int i = 0; i < data.length-1; i++) {
            boolean flag = false;
            for (int j = 0; j < data.length - i - 1; j++) {
                if(data[j]>data[j+1]){
                    int tmp = data[j];
                    data[j]=data[j+1];
                    data[j+1]=tmp;
                    flag = true;
                }
            }
            // 如果某趟没有发生交换,则表明已经处于有序状态
            if(!flag){
                break;
            }
        }
        System.out.println(Arrays.toString(data));

    }


}

5.插入排序

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc: 插入排序
 * Date: Created in 18-9-5 下午2:43
 */
public class InsertSort {
    public static void main(String[] args){
        int[] data = {77,19,80,79,20,11};
        // 依次从第二个到末尾取出数字来插入前面已排好的队列中
        for (int i = 1; i < data.length; i++) {
            // 当整体后移时,保证data[i]的值不会丢失
            int tmp = data[i];
            // i 索引处的值已经比前面的所有值都大,表明已经有序,无需插入
            // (i-1索引之前的数据已经有序,i-1索引处元素的值就是最大值)
            if(data[i]<data[i-1]){
                int j = i-1;
                // 整体后移一格
                for (; j>=0 && data[j]>tmp ; j--) {
                    data[j+1] = data[j];
                }
                // 最后将tmp的值插入到合适的位置
                data[j+1] = tmp;
            }
        }

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

6.希尔排序

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc: 希尔排序 根据增量来分组排序 (稳定)
 * Date: Created in 18-9-6 上午11:30
 */
public class ShellSort {
    public static void main(String[] args){
        int[] data = {5,7,8,3,1,2,4,6};
        // 增量increment任取,但通常为data.length/2 本例其取值为4,2,1,当增量为1时就是典型的直接插入排序了,为4和2时就是大跨度的插入排序
        // 思想:先粗排后细排
        for (int increment = data.length/2; increment > 0 ; increment/=2) {
            // insert sort
            for (int i = increment; i < data.length; i++) {
                int inserted = data[i];
                int j=i-increment;
                for ( ;j >= 0 && inserted<data[j];j-=increment) {
                    data[j+increment] = data[j];
                }
                data[j+increment] = inserted;
            }
        }
        System.out.println(Arrays.toString(data));
    }
}
// 执行过程:
// 第一次 划分为四个序列,每个序列有两个数进行排序
// 第二次 划分为二个序列,每个序列有四个数进行排序
// 第三次 划分为一个序列,每个序列有八个数进行排序
// {5,7,8,3,1,2,4,6}
// 增量 4  2  1
/********增量为4*****/
//序列为:{1,5} {7,2} {8,4} {3,6} 
// {1,7,8,3,5,2,4,6}
// {1,2,8,3,5,7,4,6}
// {1,2,4,3,5,7,8,6}
// {1,2,4,3,5,7,8,6}
/********增量为2*****/
//序列为:{1,4,5,8} {2,3,7,6}
// {1,2,4,3,5,7,8,6}
// {1,2,4,3,5,7,8,6}
// {1,2,4,3,5,7,8,6}
// {1,2,4,3,5,7,8,6}
// {1,2,4,3,5,7,8,6}
// {1,2,4,3,5,6,8,7}
/********增量为1*****/
//序列为:{1,2,4,3,5,6,8,7}
// {1,2,4,3,5,6,8,7}
// {1,2,4,3,5,6,8,7}
// {1,2,3,4,5,6,8,7}
// {1,2,3,4,5,6,8,7}
// {1,2,3,4,5,6,8,7}
// {1,2,3,4,5,6,8,7}
// {1,2,3,4,5,6,7,8}

//in a word: 除了最后一次直接插入排序外,前面都是从左往右根据下标增量进行取元素比较

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc: Shell排序 优化版
 * Date: Created in 18-9-6 上午9:24
 */
public class TestDemo {
    public static void main(String[] args){

        int[] data = {34,12,6,17,19,10,9,21,13,14};
        // 求h的最大值 ,H = 3*h+1;(h>0,H<data.length)
        int h = 1;
        while ((3*h+1)<data.length){
            h = 3*h+1;
        }
        // 逐渐减小间隔值
        while (h>0){
            for (int i = h;i<data.length;i++){
                int tmp = data[i];
                int j = i-h;
                for (;j>=0 && tmp<data[j];j-=h){
                    data[j+h] = data[j];
                }
                data[j+h] = tmp;
            }
            h = (h-1)/3;
        }

        System.out.println(Arrays.toString(data));

    }
}
//shell排序:
//    0.默认设置增量h=1;
//    1.按一定的规则找到最大增量(最优:H=3*h+1,h>0,H<data.length);
//    2.根据h遍历以h为下标的元素到数组的末尾元素并与首元素向后依次进行比较(从data[h]到data[len-1]跨增量两两比较);
//    3.缩小增量重复步骤2和3,直到h<1

7.归并排序

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc: 归并排序
 * Date: Created in 18-9-6 上午9:24
 */
public class TestDemo {
    public static void main(String[] args){

        int[] data = {21,30,49,30,97,62,72,8,37,16,54};
        mergeSort(data,0,data.length - 1);
        System.out.println(Arrays.toString(data));

    }

    private static void mergeSort(int[] data, int left, int right) {
        if(left < right){
            // 找出中间索引
            int center = (left+right)/2;
            // 对左边的进行递归
            mergeSort(data,left,center);
            // 对右边的进行递归
            mergeSort(data,center+1,right);
            // 合并
            merge(data,left,center,right);

        }

    }

    private static void merge(int[] data, int left, int center, int right) {
        int[] tmpArr = new int[data.length];
        int mid = center+1;
        int third = left;
        int tmp = left;
        while (left<=center && mid<=right){
            // 从两个数组中取出小的放入中间数组
            if(data[left]<=data[mid]){
                tmpArr[third++] = data[left++];
            }else {
                tmpArr[third++] = data[mid++];
            }
        }
        // 剩余部分依次放入中间数组
        while (mid<=right){
            tmpArr[third++] = data[mid++];
        }
        while (left<=center){
            tmpArr[third++] = data[left++];
        }
        // 将中间数组中的内容复制回原数组
        // (原left至right范围的内容复制回原数组)
        while (tmp<=right){
            data[tmp] = tmpArr[tmp++];
        }
    }
}

8.快速排序

package com.xtm.main;

import java.util.Arrays;

/**
 * Author: TianMing.Xiong
 * Desc: 快速排序
 * Date: Created in 18-9-11 上午10:13
 */
public class QuickSort {
    public static void main(String[] args){
        int[] data = {21, 30, 49, 30, 97, 62, 72, 8, 37, 16, 54};
        quickSort(data,0,data.length-1);
        System.out.println(Arrays.toString(data));
    }

    private static void quickSort(int[] data, int start, int end) {
        if(start<end){// recursion end condition
            int base = data[start];// 取第一个为基准点
            int i = start;// 后移指针,找到大于基准的数
            int j = end+1;// 前移指针,找到小于基准的数
            while (true){
                while (i<end && data[++i]<base);
                while (j>start && data[--j]>base);
                if(i<j){// 交换i和j处元素
                    int tmp = data[i];
                    data[i] = data[j];
                    data[j] = tmp;
                }else {
                    break;
                }
            }
            // 基准点和碰撞位置进行交换(相遇位置i=j)
            int tmp = data[j];
            data[j] = base;
            data[start] = tmp;
            // 此时和基准点交换的位置元素位置已经确定,此元素前面和后面的元素继续进行快排
            quickSort(data,start,j-1);
            quickSort(data,j+1,end);
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值