public abstract class IArraySort {
//排序
public abstract int[] sort(int[] sourceArray);
public void swap(int arr[],int i,int j){
int temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
public void printArr(int arr[]){
for (int i : arr) {
System.out.print(i + " ");
}
}
}
希尔排序
/**
* 选择一个增量序列 t1,t2,..tk , 其中ti>tj,且tk=1
* 按增量序列个数k,对序列进行k趟排序
* 每趟排序,根据对应的增量ti,将待排序序列分割成若干个长度为ti的子序列,分别对各子序列进行直接插入排序
* ,当增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列长度
*
* 增量序列 初始化, gap = len/2 ; gap = gap/2
*/
public class ShellSort extends IArraySort {
public static void main(String[] args) {
int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
ShellSort shellSort = new ShellSort();
int result[] = shellSort.sort(sourceArray);
shellSort.printArr(result);
}
public int[] sort(int[] sourceArray) {
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
int gap = arr.length/2;
int j,newNumber;
while(gap>0){
//对子序列进行插入排序
for (int i=gap;i<arr.length;i++){
j = i;
newNumber=arr[j];
while(j>=gap&&newNumber<arr[j-gap]){
arr[j] = arr[j-gap];
j = j-gap; //注意这里不是j--。而是隔gap
}
if (j!=i)
arr[j] = newNumber;
}
gap=gap/2; //缩小增量序列
}
return arr;
}
}
归并排序--递归实现
//归并排序---递归实现
// 1--3 2--4 ==》 1--2--3--4
/**
* 1. 申请临时空间,大小为待排序数组的大小,该空间用来存放合并后的序列
* 2. 分: 将数组一分为2 (1,2,3,4) middle=(0+3)/2=1
* 3. 递归的进行【分】操作,直到序列的长度为1
* 4. 合: 将序列1和序列2合并到临时数组中,并将临时数组的数据导回原数组Arr
*/
public class MergeSortDemo extends IArraySort{
public static void main(String[] args) {
int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
MergeSortDemo mergeSort = new MergeSortDemo();
int[] result = mergeSort.sort(sourceArray);
mergeSort.printArr(result);
}
public int[] sort(int[] sourceArray) {
int tempArr[] = new int[sourceArray.length];
return MergeSort(sourceArray,tempArr,0,sourceArray.length-1);
}
/**
* 归并排序
* @param arr 待排序数组
* @param tempArr 临时数组
* @param low 待排序数组起始位置
* @param high 待排序数组结束位置
* @return
*/
private int[] MergeSort(int arr[],int tempArr[],int low,int high){
//递归出口:当子序列只有一个元素时
if (low<high){
//1. 分: 将数组一分为2 (1,2,3,4) middle=(0+3)/2=1
int middle = (low+high)/2;
MergeSort(arr,tempArr,low,middle);
MergeSort(arr,tempArr,middle+1,high);
//2. 合: 在临时数组中将子序列进行归并,并将结果导入arr
Merge(arr,tempArr,low,middle,high);
}
return arr;
}
/**
* 合并子序列 1--3 2--4 ==》 1--2--3--4
* @param arr 待排序数组
* @param tempArr 临时数组
* @param low 第一个子序列起始下标
* @param middle 第一个子序列结束下标
* @param high 第二个子序列结束下标
*/
private void Merge(int[] arr, int[] tempArr, int low, int middle, int high) {
int i=low; //标志第一个子序列当前元素
int j=middle+1; //标志第二个子序列当前元素
int index=low;
while (i<=middle&&j<=high){
if (arr[i]<=arr[j])
tempArr[index++] = arr[i++];
else
tempArr[index++] = arr[j++];
}
//跳出循环2种可能, 两个子序列合并完了; 一个子序列合并完了;
while (i<=middle) //子序列1没完,把剩余元素全加进来
tempArr[index++]=arr[i++];
while (j<=high)
tempArr[index++]=arr[j++];
//比较关键:将排好序后的临时数组中的元素重新导入到arr
for (int k=low;k<=high;k++)
arr[k]=tempArr[k];
}
}
归并排序--非递归实现
//归并排序 --非递归实现
//1. 申请临时空间tempArr, 第一次合并后将数组从arr导入tempArr, 第二次合并将数组从tempArr导入arr
//1. 取2,4,8...个元素为一组,进行合并
public class MergeSortDemo2 extends IArraySort{
public static void main(String[] args) {
int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
MergeSortDemo2 mergeSort = new MergeSortDemo2();
int[] result = mergeSort.sort(sourceArray);
mergeSort.printArr(result);
}
public int[] sort(int[] sourceArray) {
int tempArr[] = new int[sourceArray.length];
return MergeSort(sourceArray,tempArr);
}
/**
* 归并排序
* @param arr 待排序数组
* @param tempArr 临时数组
* @return
*/
private int[] MergeSort(int arr[],int tempArr[]){
int length=1;
while (length<=arr.length){
MergePass(arr,tempArr,length); //将待排序数组归并到临时数组
length = length * 2;
MergePass(tempArr,arr,length); //将临时数组归并到待排序数组
length = length * 2;
}
return arr;
}
//将待排序数组src 归并 到target数组
private void MergePass(int[] src, int[] target, int length) {
int N = src.length;
int i;
for(i=0;i<=N-2*length;i+=length*2){
//归并指定长度子序列 如长度为2=>下标:0 1 3
Merge(src,target,i,i+length-1,i+2*length-1);
}
//剩余元素不够划分
if (i+length<=N){
//还剩2个子序列,其中第二个子序列不满
Merge(src,target,i,i+length-1,N-1);
}else {
//还剩下1个子序列
for (int j=i;j<N;j++)
target[j]=src[j];
}
}
/**
* 合并子序列 1--3 2--4 ==》 1--2--3--4
* @param arr 待排序数组
* @param tempArr 临时数组
* @param low 第一个子序列起始下标
* @param middle 第一个子序列结束下标
* @param high 第二个子序列结束下标
*/
private void Merge(int[] arr, int[] tempArr, int low, int middle, int high) {
int i=low; //标志第一个子序列当前元素
int j=middle+1; //标志第二个子序列当前元素
int index=low;
while (i<=middle&&j<=high){
if (arr[i]<=arr[j])
tempArr[index++] = arr[i++];
else
tempArr[index++] = arr[j++];
}
//跳出循环2种可能, 两个子序列合并完了; 一个子序列合并完了;
while (i<=middle) //子序列1没完,把剩余元素全加进来
tempArr[index++]=arr[i++];
while (j<=high)
tempArr[index++]=arr[j++];
//比较关键:将排好序后的临时数组中的元素重新导入到arr
/*for (int k=low;k<=high;k++)
arr[k]=tempArr[k];*/
}
}
快速排序
//快速排序
/**
* 1. 选主元pivot
* 2. 划分左右子集, 所有比pivot小的放在左边,比pivot大的元素放右边。 这个称为分区(partition)操作
* 3. 递归地将左子集和右子集进行快速排序
*/
public class QuickSort extends IArraySort {
public static void main(String[] args) {
int[] sourceArray = {20,40,32,67,33,1,40,20,89,300,400,15,15,2,1,20,89,400};
QuickSort quickSort = new QuickSort();
int[] result = quickSort.sort(sourceArray);
quickSort.printArr(result);
}
public int[] sort(int[] sourceArray) {
return quickSort(sourceArray,0,sourceArray.length-1);
}
private int[] quickSort(int[] arr,int left,int right){
if (left<right){
int partitionIndex = partition(arr,left,right); //分区,并返回pivot下标
quickSort(arr,left,partitionIndex-1); //递归对左子集进行快速排序
quickSort(arr,partitionIndex+1,right); //递归对右子集进行快速排序
}
return arr; //递归出口,子集只有一个元素
}
private int partition(int[] arr,int left,int right){
//设置基准值pivot
int pivot = left;
int i=pivot+1;
int j=right;
while (i<j){
while (i<j&&arr[i]<=arr[pivot]) i++;
while (i<j&&arr[j]>arr[pivot]) j--;
//冲突,交换i和j
if (i<j){
swap(arr,i,j);
i++;j--;
}
}
if (arr[i]>=arr[pivot]){
swap(arr,pivot,i-1);
return i-1;
}else {
swap(arr,pivot,i);
return i;
}
}
}