[Turn] Implementation of the third Hill sort in the vernacular classic algorithm series

From: http://blog.csdn.net/morewindows/article/details/6668714

 

The essence of Hill sorting is grouping insertion sorting, which is also called shrinking incremental sorting, because DL. Shell was named after it was proposed in 1959.

 

The basic idea of ​​this method is: first divide the entire sequence of elements to be sorted into several subsequences (composed of elements separated by a certain "increment") for direct insertion sorting, and then reduce the increments in turn before sorting, and wait for the entire When the elements in the sequence are basically ordered (the increment is small enough), perform a direct insertion sort on all the elements. Because direct insertion sorting is very efficient when the elements are basically ordered (close to the best case), Hill sorting has a greater improvement in time efficiency than the first two methods.

 

Take an array 49, 38, 65, 97, 26, 13, 27, 49, 55, 4 with n=10 as an example

first gap = 10 / 2 = 5

49   38   65   97   26   13   27   49   55   4

1A                                        1B

        2A 2B

                 3A 3B

                         4A 4B

                                  5A                                         5B

1A, 1B, 2A, 2B, etc. are grouping marks. The same numbers indicate that they are in the same group. The capital letters indicate the number of elements in the group. The data of the same group is directly inserted and sorted each time. That is, it is divided into five groups (49, 13) (38, 27) (65, 49) (97, 55) (26, 4) so ​​that each group becomes (13, 49) (27, 38) ( 49, 65) (55, 97) (4, 26), the same below.

The second gap = 5 / 2 = 2

after sorting

13   27   49   55   4    49   38   65   97   26

1A             1B             1C              1D            1E

        2A 2B 2C 2D 2E

The third gap = 2 / 2 = 1

4   26   13   27   38    49   49   55   97   65

1A   1B     1C    1D    1E      1F     1G    1H     1I     1J

The fourth time gap = 1 / 2 = 0 is sorted to get the array:

4   13   26   27   38    49   49   55   65   97

 

The following gives the Hill ordering written strictly by definition

void shellsort1(int a[], int n)
{
	int i, j, gap;

	for (gap = n / 2; gap > 0; gap /= 2) //步长
		for (i = 0; i < gap; i++) //loop through each group, the group number is [0..gap-1]
		{//The following is insertion sort
			for (j = i + gap; j < n; j += gap)//here j=i+gap is to obtain each element in this group, because the distance between elements in the same group is the step size of the gap
				if (a[j] < a[j - gap])
				{
					int temp = a[j];
					int k = j - gap;
					while (k >= 0 && a[k] > temp)
					{
						a[k + gap] = a[k];
						k -= gap;
					}
					a[k + gap] = temp;
				}
		}
}

 很明显,上面的shellsort1代码虽然对直观的理解希尔排序有帮助,但代码量太大了,不够简洁清晰。因此进行下改进和优化,以第二次排序为例,原来是每次从1A到1E,从2A到2E,可以改成从1B开始,先和1A比较,然后取2B与2A比较,再取1C与前面自己组内的数据比较…….。这种每次从数组第gap个元素开始,每个元素与自己组内的数据进行直接插入排序显然也是正确的。

void shellsort2(int a[], int n)
{
	int j, gap;
	
	for (gap = n / 2; gap > 0; gap /= 2)
		for (j = gap; j < n; j++)//从数组第gap个元素开始
			if (a[j] < a[j - gap])//每个元素与自己组内的数据进行直接插入排序
			{
				int temp = a[j];
				int k = j - gap;
				while (k >= 0 && a[k] > temp)
				{
					a[k + gap] = a[k];
					k -= gap;
				}
				a[k + gap] = temp;
			}
}

 附注:上面希尔排序的步长选择都是从n/2开始,每次再减半,直到最后为1。其实也可以有另外的更高效的步长选择,如果读者有兴趣了解,请参阅维基百科上对希尔排序步长的说明:

http://zh.wikipedia.org/wiki/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327077235&siteId=291194637