package edu.mit.sort;
import java.util.Random;
public class SortUtils {
public static void main(String[] args) {
//int[] arr = {6,10,13,5,8,3,2,11};
int[] arr = {5,5,2,1,3,7,6,6,9,11,14,12,12,12,10,13,10};
System.out.print("排序前:");
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
//bubbleSort(arr);
//insertSort(arr);
//mergeSort(arr,0,arr.length-1,new int[arr.length]);
//randomQuickSort(arr,0,arr.length-1);
countSort(arr);
System.out.print("排序后:");
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
/*int[] a1 = {1,3,5,7,9};
int[] a2 = {2,4,6,8,10};
int[] arr = mergeSort(a1,a2);
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}*/
}
/**
* for i = 0 to n
* for j = i+1 to n
* do if arr[j]<arr[i]
* then exch arr[j]<->arr[i]
*
* 每次外循环,arr[i->n]中最小的元素都会被交换到前面<br/>
* 时间复杂度O(n^2)
* @param arr
*/
public static void bubbleSort(int[] arr){
int n = arr.length;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(arr[i]>arr[j]){
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
}
}
}
}
/**
* for j = 1 to n
* i <-- j,tmp = a[j]
* while i>0 && a[j] < a[i-1]
* a[i] <-- a[i-1]; i--;
* a[i] = tmp;
*
* ⒈ 从第一个元素开始,该元素可以认为已经被排序
* ⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描
* ⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置
* ⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
* ⒌ 将新元素插入到下一位置中
* ⒍ 重复步骤2
* 时间复杂度O(n^2)
* @param arr
*/
public static void insertSort(int[] arr){
int n = arr.length;
for(int j=1;j<n;j++){
int i = j;
int tmp = arr[j];//insert element
while(i>0&&tmp<arr[i-1]){
arr[i] = arr[i-1];//move to next position
i--;
}
arr[i] = tmp;
}
}
/**
* 归并排序 时间复杂度O(nlgn)
* @param arr 要排序的数组
* @param begin 起始点(包含)
* @param end 结束点(包含)
* @param tmp 存放中间结果,最后作为返回值
*/
public static void mergeSort(int[] arr,int begin,int end,int[] tmp){
if(begin<end){
int mid = (begin+end)/2;
mergeSort(arr,begin,mid,tmp);//相当于左子树
mergeSort(arr,mid+1,end,tmp);
int i=begin,j=mid+1;
int k=begin;
while(i<=mid && j<=end){//每次选最小的
if(arr[i]<arr[j]){
tmp[k++] = arr[i++];
}else{
tmp[k++] = arr[j++];
}
}
while(i<=mid){//剩下的
tmp[k++] = arr[i++];
}
while(j<=end){//剩下的
tmp[k++] = arr[j++];
}
for(i=begin;i<=end;i++){//写回原数组
arr[i] = tmp[i];
}
}
}
/**
* 时间复杂度O(n+m)
* @param a1
* @param a2
* @return
*/
public static int[] mergeSort(int[] a1,int[] a2){
int len1 = a1.length;
int len2 = a2.length;
int len = len1 + len2;
int[] a = new int[len];
int i=0,j=0,k=0;
while(i<len1 && j<len2){//每次选最小的
if(a1[i]<a2[j]){
a[k] = a1[i];
i++;
}else{
a[k] = a2[j];
j++;
}
k++;
}
while(i<len1){//剩下的
a[k++] = a1[i++];
}
while(j<len2){//剩下的
a[k++] = a2[j++];
}
return a;
}
public static void quickSort(int[] arr,int begin,int end){
int key = arr[begin];//pivot
int i = begin;
for(int j=begin+1;j<=end;j++){
if(arr[j]<key){// 小于关键字的都丢到左边
i++;
if(i!=j){
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
}
}
}
//比关键字放到i处,使得大于key的都在左边,小于key的都在右边
if(i!=begin){
arr[i] = arr[i]^arr[begin];
arr[begin] = arr[i]^arr[begin];
arr[i] = arr[i]^arr[begin];
}
if(i-begin>1){
quickSort(arr,begin,i-1);
}
if(end-i>1){
quickSort(arr,i+1,end);
}
}
public static void randomQuickSort(int[] arr,int begin,int end){
Random r= new Random();
int pos = begin + r.nextInt(end-begin);
int key = arr[pos];//pivot
int i = begin;
for(int j=begin+1;j<=end;j++){
if(arr[j]<key){// 小于关键字的都丢到左边
i++;
if(i!=j){
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
}
}
}
//比关键字放到i处,使得大于key的都在左边,小于key的都在右边
if(i!=begin){
arr[i] = arr[i]^arr[begin];
arr[begin] = arr[i]^arr[begin];
arr[i] = arr[i]^arr[begin];
}
if(i-begin>1){
quickSort(arr,begin,i-1);
}
if(end-i>1){
quickSort(arr,i+1,end);
}
}
/**
* 适用于数组中最大元素比较小,数据比较集中的情况
* @param arr
*/
public static void countSort(int[] arr){
int[] tmp = new int[arr.length];
int[] counts = new int[1024];//假设arr中的元素都小于1024
for(int i=0;i<arr.length;i++){
counts[arr[i]]++;
}
for(int i=1;i<1024;i++){
counts[i] = counts[i] + counts[i-1];
}
for(int i=0;i<arr.length;i++){
if(counts[arr[i]]>0){
tmp[counts[arr[i]]-1] = arr[i];
counts[arr[i]]--;
}
}
for(int i=0;i<arr.length;i++){//写回原数组
arr[i]=tmp[i];
}
}
/**
* 适用于数组元素长度相同的情况
* 先对个位排序,再十位,然后百位..借助于计数排序的原理,轮询次数为数的长度,如果借助较大
* 辅助空间(多位一组)可以让其更快,时间复杂度为O(n)
*
* @param arr
*/
public static void baseCount(int[] arr){
//...
}
}