【算法】算法第四版学习笔记 -- 希尔排序

希尔排序是基于插入排序的算法

排序算法类模板:

https://blog.csdn.net/chenghan_yang/article/details/83002422

希尔排序的步骤

  1. 确定分组间隔,并确定递增序列
  2. 对原数组进行等间隔分组,遵循一定的规则,类似于{n1,n2,n3,n4,n5,n6} 以3为间隔,可分为{n1,n4}、{n2,n5}、{n3,n6}
  3. 对分组内的元素进行插入排序
  4. 重复1和2,直到分组间隔减为1

package sort;

public class Example {
	public static boolean less(Comparable v, Comparable w) {
		return v.compareTo(w) < 0;
	}
	
	public static void exch(Comparable[] a, int i, int j) {
		Comparable t = a[i]; 
		a[i] = a[j];
		a[j] = t;
	}
	
	public static void show(Comparable[] a) {
		for(int i = 0; i<a.length; i++) {
			System.out.print(a[i] + " ");
		}
	}
	
	public static boolean isSorted(Comparable[] a) {
		for(int i = 1; i < a.length; i++) {
			if(less(a[i],a [i-1])) return false;
		}
		return false;
	}

}

package shell_sort;

import java.util.Arrays;
import sort.Example;

public class Shell extends Example
{	
	
	public static void sort(Comparable[] a)
	{	
		int N = a.length;
		int h = 1;
		while (h < N/3) h = 3*h + 1; 
		int count1 = 0;
		int count2 = 0;
		
		while (h >= 1) 
		{	
			System.out.println("【轮次】——————————下面进行——————————" + ++count1 +"轮排序" + "初始序列为" + Arrays.toString(a));
			System.out.println();
			for (int i = h; i < N; i++)
			{	
				
				for(int j = i; j >= h && less(a[j], a[j-h]); j -= h)
				{	
					System.out.println("--进行" + count1 +"轮排序" +"中的" + ++count2 + "次交换");
					System.out.println("【交换的元素】为【" + a[j] + "】和【" + a[j-h] + "】");
					exch(a, j, j-h);
					System.out.println(Arrays.toString(a));
					System.out.println();
				}	
				
			}
			count2 = 0;
			h=h/3;
			
		}
		
	}
}


package shell_sort;

public class Test {

	public static void main(String[] args) {
		Integer[] a = {1,66,7,4,8,9,3,25,64,13,65,13,86,42,56} ;
		Shell.sort(a);
		
	}

}

---

【轮次】——————————下面进行——————————1轮排序初始序列为[1, 66, 7, 4, 8, 9, 3, 25, 64, 13, 65, 13, 86, 42, 56]

--进行1轮排序中的1次交换
【交换的元素】为【56】和【66[1, 56, 7, 4, 8, 9, 3, 25, 64, 13, 65, 13, 86, 42, 66]

【轮次】——————————下面进行——————————2轮排序初始序列为[1, 56, 7, 4, 8, 9, 3, 25, 64, 13, 65, 13, 86, 42, 66]

--进行2轮排序中的1次交换
【交换的元素】为【9】和【56[1, 9, 7, 4, 8, 56, 3, 25, 64, 13, 65, 13, 86, 42, 66]

--进行2轮排序中的2次交换
【交换的元素】为【3】和【7[1, 9, 3, 4, 8, 56, 7, 25, 64, 13, 65, 13, 86, 42, 66]

--进行2轮排序中的3次交换
【交换的元素】为【13】和【56[1, 9, 3, 4, 8, 13, 7, 25, 64, 56, 65, 13, 86, 42, 66]

--进行2轮排序中的4次交换
【交换的元素】为【13】和【25[1, 9, 3, 4, 8, 13, 7, 13, 64, 56, 65, 25, 86, 42, 66]

--进行2轮排序中的5次交换
【交换的元素】为【42】和【56[1, 9, 3, 4, 8, 13, 7, 13, 64, 42, 65, 25, 86, 56, 66]

【轮次】——————————下面进行——————————3轮排序初始序列为[1, 9, 3, 4, 8, 13, 7, 13, 64, 42, 65, 25, 86, 56, 66]

--进行3轮排序中的1次交换
【交换的元素】为【3】和【9[1, 3, 9, 4, 8, 13, 7, 13, 64, 42, 65, 25, 86, 56, 66]

--进行3轮排序中的2次交换
【交换的元素】为【4】和【9[1, 3, 4, 9, 8, 13, 7, 13, 64, 42, 65, 25, 86, 56, 66]

--进行3轮排序中的3次交换
【交换的元素】为【8】和【9[1, 3, 4, 8, 9, 13, 7, 13, 64, 42, 65, 25, 86, 56, 66]

--进行3轮排序中的4次交换
【交换的元素】为【7】和【13[1, 3, 4, 8, 9, 7, 13, 13, 64, 42, 65, 25, 86, 56, 66]

--进行3轮排序中的5次交换
【交换的元素】为【7】和【9[1, 3, 4, 8, 7, 9, 13, 13, 64, 42, 65, 25, 86, 56, 66]

--进行3轮排序中的6次交换
【交换的元素】为【7】和【8[1, 3, 4, 7, 8, 9, 13, 13, 64, 42, 65, 25, 86, 56, 66]

--进行3轮排序中的7次交换
【交换的元素】为【42】和【64[1, 3, 4, 7, 8, 9, 13, 13, 42, 64, 65, 25, 86, 56, 66]

--进行3轮排序中的8次交换
【交换的元素】为【25】和【65[1, 3, 4, 7, 8, 9, 13, 13, 42, 64, 25, 65, 86, 56, 66]

--进行3轮排序中的9次交换
【交换的元素】为【25】和【64[1, 3, 4, 7, 8, 9, 13, 13, 42, 25, 64, 65, 86, 56, 66]

--进行3轮排序中的10次交换
【交换的元素】为【25】和【42[1, 3, 4, 7, 8, 9, 13, 13, 25, 42, 64, 65, 86, 56, 66]

--进行3轮排序中的11次交换
【交换的元素】为【56】和【86[1, 3, 4, 7, 8, 9, 13, 13, 25, 42, 64, 65, 56, 86, 66]

--进行3轮排序中的12次交换
【交换的元素】为【56】和【65[1, 3, 4, 7, 8, 9, 13, 13, 25, 42, 64, 56, 65, 86, 66]

--进行3轮排序中的13次交换
【交换的元素】为【56】和【64[1, 3, 4, 7, 8, 9, 13, 13, 25, 42, 56, 64, 65, 86, 66]

--进行3轮排序中的14次交换
【交换的元素】为【66】和【86[1, 3, 4, 7, 8, 9, 13, 13, 25, 42, 56, 64, 65, 66, 86]



  • 代码解读 - 隐式的分组交换
  1. h = 1, while(h < N/3) { h = 3*h + 1} 假设的递增序列,当N=15, h=13。确定这样一个序列是影响性能的关键,但至今没有文献证明有性能最高的序列,所以不重点理解代。
  2. 上面确定了h, 也就确定了步长。 一轮操作后步长以h/3 递减, 也就分别是h=13, 4, 1
  3. for的两个循环,其实是对每一组进行并行的插入排序。代码并不是先确认分组再进行排序的,是每次交换元素都在分组内进行,用h为步长。如[1,66,7,4,8,9,3,25,64,13,65,13,86,42,56], N=15
    ——————————————————————————————————————
    第一轮h = 13, 可以分两组
    [1, 42]
    [66 , 56] -> [56,66]
    第一轮排序后的结果为(黄标为交换过的元素):
    [1 56 7 4 8 9 3 25 64 13 65 13 86 42 66]
    ——————————————————————————————————————
    第二轮h = 4,所有元素被分成三组,分别是
    [1 8 64 86]
    [56 9 13 42]
    [7 3 65 66]
    [4 25 13]
    第二轮排序结果为
    [1, 9, 3, 4, 8, 13, 7, 13, 64, 42, 65, 25, 86, 56, 66]
    ——————————————————————————————————————
    低三轮h = 1所有元素就是一组,进行插入排序

循环开始的三次分别定位的是三组的开头元素,所以是实现并行的插入排序


  • 实际应用

算法第四版P262:如果你需要解决一个排序问题而又没有系统排序函数可用(例如直接接触硬件或是运行于嵌入式系统中的代码),可以先用希尔排序,然后再考虑是否值得将它替换为更加复杂的排序算法

展开阅读全文

没有更多推荐了,返回首页