Shell、归并排序、递归的java实现
摘要:上篇笔记记述了四个排序:插入排序、快速排序、冒泡排序、选择排序、本篇主要记录两个:shell排序——对插入排序的改进、归并排序。同样是从思想、算法实现和java代码的实现来研究、顺道补充了点递归的东西。
一:Shell排序
1、基本思想:
Shell排序(希尔排序)是对插入排序的一种改进、也称“缩小增量排序”。他是按照一个选取的缩小增量值n将要排序的数组中元素下标相差n和n的倍数的所有元素分成n组、分别对n组元素进行插入排序、完成后按上述规则再细分n1组、n1<n、再排序、直到nx = 1、直接对这一组进行插入排序、实现Shell排序、从上边的步骤也可以看出Shell排序是对插入排序的一种改进。
2、算法原理:
a) 取数组长度的一半step=a.length/2 作为缩小增量、
b) 将数组分成 step组、
c)分别对每组进行插入排序。
d) 将step组中每组再以缩小增量step = step/2分组、重复步骤c。
e) 重复步骤c、d直到step=1、对这一组元素进行插入排序。over!
3、java实现:
package com.chy.arithmetic;
import java.util.Arrays;
public class ShellSort {
private static int ia[] = { 1, 54, 6, 3, 78, 34, 12, 45, 56, 3 };
private static int[] shellSort(int[] a) {
//the increment;
int step = a.length / 2;
// The result has mostly sorted at the previous step of step=1;
//Just change the condition step> = 1 to step > 1 if you want to observe it ;
while (step >= 1) {
for (int i = step; i < a.length; i++) {
int temp = a[i];
int j;
// use insert sort to sort the part of a;
for (j = i - step; j >= 0 && a[j] > temp; j -= step) {
a[j + step] = a[j];
}
a[j + step] = temp;
}
//narrow the increment.
step = step / 2;
}
return a;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(shellSort(ia)));
}
}
二:归并排序
1、基本思想:
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列(一般分解到原子级),再把有序的子序列合并为整体有序序列。
2、算法原理:
分解操作:
a) 申请两个空间、分别存放原来序列的一半(不是严格意义上的一半、如果元素个数是奇数、则有一方会多一个元素)。
b) 使用中间变量 center= a.length/2划分序列
c) 分别填充第一步申请的两个空间
d) 递归的形式细分填充上一步划分的两个空间、直到所有空间只放一个元素。
e) 进行归并操作
f) 重复上述步骤、直到所有空间合并成一个有序序列。
归并操作:
a)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
b)设定两个指针,最初位置分别为两个已经排序序列的起始位置
c)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指
d)针到下一位置
e)重复步骤3直到某一指针达到序列尾
f)将另一序列剩下的所有元素直接复制到合并序列尾
3、java实现:
package com.chy.arithmetic;
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] array = { 3, 2, 1, 8, 5, 7, 9, 4, 6 };
System.out.println(Arrays.toString(mergeSort(array)));
}
private static int[] mergeSort(int[] a) {
if (a.length == 1) {
return a;
}
int[] aL = new int[a.length / 2];
int[] aR = new int[a.length - a.length / 2];
int center = a.length / 2;
for (int i = 0; i < center; i++) {
aL[i] = a[i];
}
for (int i = center, j = 0; i < a.length; i++, j++) {
aR[j] = a[i];
}
int[] sortedAL = mergeSort(aL);
int[] sortedAR = mergeSort(aR);
int[] as = mergeTwoArray(sortedAL, sortedAR);
return as;
}
private static int[] mergeTwoArray(int[] aL, int[] aR) {
int i = 0;
int j = 0;
int[] a = new int[aL.length + aR.length];
int foot = 0;
while (i < aL.length && j < aR.length) {
if (aL[i] < aR[j]) {
a[foot++] = aL[i++];
} else {
a[foot++] = aR[j++];
}
}
if (i == aL.length) {
while (j < aR.length) {
a[foot++] = aR[j++];
}
} else {
while (i < aL.length) {
a[foot++] = aL[i++];
}
}
return a;
}
}
三:递归
1、基本思想:
递归在开发中是非常常见的一种算法、比如罗列某个指定文件夹下所有的文件名、因为有可能有层层文件、所以我们可以使用递归来实现。
思想:对于一个复杂的问题,把原问题分解为若干个相对简单类同的子问题,继续下去直到子问题简单到能够直接求解,也就是说到了递推的出口,这样原问题就有递推得解。
最能说明递归思想的是:Febonacci数列——看代码。
递归最重要的是1、范围要越来越小。2、是要找到出口、也就是结束条件。
2、java实现:
package com.chy.arithmetic;
import java.io.File;
public class RecursiveAlgorithm {
public static void main(String[] args) {
System.out.println(getFibonacciValue(10));
getAllFiles("D:\\upload");
}
/**
* to obtain the specified index of a Fibonacci's value
*/
private static long getFibonacciValue(int index) {
if (index == 1 || index == 2) {
return 1;
} else {
return getFibonacciValue(index - 1) + getFibonacciValue(index - 2);
}
}
/**
* to obtain all files in a specified directory
*/
private static void getAllFiles(String filePath){
File file = new File(filePath);
if(!file.isDirectory()){
System.out.println(file.getAbsolutePath());
}else{
File[] fileList = file.listFiles();
for(File fileDetail : fileList){
if(!fileDetail.isDirectory()){
System.out.println(fileDetail.getAbsolutePath());
}else{
getAllFiles(fileDetail.getAbsolutePath());
}
}
}
}
}