算法(3)
直接插入,希尔排序,归并排序
首先是直接插入:很现实的例子就是斗地主,拿到一手乱牌,从第一张看起,然后是第二张,然后比较,前两张的大小,然后排序,
比较简单的一种排序
java代码实现:
private static void InsertSort(int[] a) {
// 无需序列
int temp;
int j;
for (int i = 1; i < a.length; i++) {
if (a[i] < a[i - 1]) {
temp = a[i];
for (j = i - 1; j >= 0; j--) {
a[j+1]=a[j];
}
a[j+1]=temp;
}
}
}
同样的测试数量:216ms
排序效率拙计啊。
希尔排序:
当数组是5,4,3,2,1时候插入排序,每一次就都要移动十分的烦人,效率十分底下,shell根据这个弱点进行了算法改进,融入了一种叫做“缩小增量排序法”的思想,其实也蛮简单的,不过有点注意的就是:增量不是乱取,而是有规律可循的。
增量的选取:
第一次:d=count/2
第二次:d=(count/2)/2
最后:d=1;
上面的的现象:
d=3:40-50不交换,20-30不交换,80-60交换 最后40,20,60,50,30,80
d=2:40-60不交换,60-30交换,此时40-30再次交换,20-50不交换,50-80不交换 30,20,40,50,60,80
d=1:30-20交换30-40不交换,40-50不交换,50-60不交换,60-80不交换 20,30,40,50,60,80
希尔排序是插入排序的改进版本。
java实现:
// 希尔排序
private static void ShlleSort(int[] a) {
int step=a.length/2;//增量
while(step>=1){
for(int i=step;i<a.length;i++){
int temp=a[i];
int j;
for(j=i-step;j>=0&&temp<a[j];j=j-step){
a[j+step]=a[j];
}
a[j+step]=temp;
}
step=step/2;
}
}
private static void ShlleSort(int[] a) {
int step=a.length/2;//增量
while(step>=1){
for(int i=step;i<a.length;i++){
int temp=a[i];
int j;
for(j=i-step;j>=0&&temp<a[j];j=j-step){
a[j+step]=a[j];
}
a[j+step]=temp;
}
step=step/2;
}
}
运行时间:38;
下面是归并排序:归并排序是非常明显的算法设计分治法的一种。
分治法的思想:由一个大规模的问题分解成,互不相干的规模小的子问题,然后把小的问题在分。这是分
治:分解了之后就要解决了,治就是解决,这里应用的就是排序,把分解的最小单位来解决排序
合并:最后一步就是合并了,把排序好的若干个小问题合并,在排序。最后解决。
那么我们来看看归并排序:
归并排序分两步:
1.分,将数组尽可能的分,一直到原子级别。
2.并,将原子级别的数两两合并排序,最后产生结果。
// 归并排序
// 第一步数组的划分
private static void MergeSort(int[] a, int[] temparray, int left, int right) {
if (left < right) {
int middle = (left + right) / 2;
// 递归的划分数组左序列
MergeSort(a, temparray, left, middle);
// 递归的划分数组右序列
MergeSort(a, temparray, middle + 1, right);
// 数组合并操作
Merge(a, temparray, left, middle + 1, right);
}
}
// 数组两两合并
private static void Merge(int[] a, int[] temparray, int left, int middle,
int right) {
int leftEnd = middle-1;
int rightStart = middle;
int tempIndex = left;
int tempLength = right - left + 1;
// 先循环两个区间都没有结束的情况
while ((left <= leftEnd) && (rightStart <= right)) {
if (a[left] < a[rightStart]) {
temparray[tempIndex++] = a[left++];
} else {
temparray[tempIndex++] = a[rightStart++];
}
}
// 判断左序列是否结束
while (left <= leftEnd) {
temparray[tempIndex++] = a[left++];
}
// 判断右序列是否结束
while (rightStart <= right) {
temparray[tempIndex++] = a[rightStart++];
}
// 交换数据
for (int i = 0; i < tempLength; i++) {
a[right] = temparray[right];
right--;
}
}
// 第一步数组的划分
private static void MergeSort(int[] a, int[] temparray, int left, int right) {
if (left < right) {
int middle = (left + right) / 2;
// 递归的划分数组左序列
MergeSort(a, temparray, left, middle);
// 递归的划分数组右序列
MergeSort(a, temparray, middle + 1, right);
// 数组合并操作
Merge(a, temparray, left, middle + 1, right);
}
}
// 数组两两合并
private static void Merge(int[] a, int[] temparray, int left, int middle,
int right) {
int leftEnd = middle-1;
int rightStart = middle;
int tempIndex = left;
int tempLength = right - left + 1;
// 先循环两个区间都没有结束的情况
while ((left <= leftEnd) && (rightStart <= right)) {
if (a[left] < a[rightStart]) {
temparray[tempIndex++] = a[left++];
} else {
temparray[tempIndex++] = a[rightStart++];
}
}
// 判断左序列是否结束
while (left <= leftEnd) {
temparray[tempIndex++] = a[left++];
}
// 判断右序列是否结束
while (rightStart <= right) {
temparray[tempIndex++] = a[rightStart++];
}
// 交换数据
for (int i = 0; i < tempLength; i++) {
a[right] = temparray[right];
right--;
}
}

浙公网安备 33010602011771号