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);
}
}
}