0
点赞
收藏
分享

微信扫一扫

springboot 集成log4j日志,需要自定义json格式内容输出方便ES采集

目录

1、常见排序算法

1.1 插入排序基本思想

2、希尔排序

2.1 希尔排序( 缩小增量排序 )

2.1.1 预排序阶段

2.1.2 插入排序阶段

2.2 单趟希尔排序

2.2.1 思路分析

2.2.2 代码实现

3、希尔排序代码实现

4、希尔排序时间复杂度

5、希尔排序与插入排序效率对比

6、希尔排序特性总结


1、常见排序算法

1.1 插入排序基本思想

 

2、希尔排序

2.1 希尔排序( 缩小增量排序 )

我们画图来分析一下:我们这里是排升序

由图我们其实可以看出来,当最后一次gap=1时,本质是插入排序,而希尔排序就是先预排序,最后再插入排序一次就实现了排序

我们将上面的图来分析一下:

2.1.1 预排序阶段

1、第一趟,当gap=5时,意思是每间隔5个数为一组,9与4,1与8,2与6,5与3,7与5分为一组,当后面的数字小于前面的数字我们就交换,这样我们就将这几组中小的数字排到了前面,大的数字就排到了后面;

2、第二趟,我们就让gap = gap/3+1(这里gap/3+1是为了最后能得到gap=1,当gap<3时,如果只是除以3,得到的就是0,这样就实现不了完全排序),gap=2,每间隔2个数为一组,4与2,5,8,5一组,1与3,9,6,7一组,比较大小,然后交换;

2.1.2 插入排序阶段

3、当调整gap=1时,本质就是插入排序了,这时经过了之前的预排序阶段,我们的数字已经接近有序了,但是不完全有序,此时上插入排序,效率提升会很大。

2.2 单趟希尔排序

2.2.1 思路分析

单趟的希尔排序其实就是将相隔为gap的数字分为一组,先进行排序。

画图分析:

 

将单趟的每个间隔为gap的数字分为一组先进行排序。

2.2.2 代码实现

for (int i = 0; i < n - gap; i++)//多组一起排序(没有提升效率,只是少写一组循环)
{
    int end = i;
    int tmp = a[i + gap];
    while (end >= 0)
    {
        if (a[end] > tmp)
        {
            a[end + gap] = a[end];
            end -= gap;
        }
        else
        {
            break;
        }
    }
    a[end + gap] = tmp;
}

3、希尔排序代码实现

给单趟排序外面加一层循环,让gap不断缩小,直到为 1,就实现了希尔排序。

void ShellSort(int* a, int n)
{
	//1. 当 gap > 1 时先进性预排序
	//2. 当 gap == 1 时直接插入排序
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;// +1可以保证最后一次一定是1
		for (int i = 0; i < n - gap; i++)//多组一块进行
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

4、希尔排序时间复杂度

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的希尔排序的时间复杂度都不固定 。

以下是两本书对希尔排序时间复杂度的描述:

我们这里的gap是按照Knuth提出的方式取值的,而且Knuth进行了大量的试验统计,我们暂时就按照:O(n^1.25)到O(1.6*n^1.25)来算。

5、希尔排序与插入排序效率对比

我们分别开辟两个数组,都是100000大小,使用希尔排序与插入排序,对比所消耗的时间。

//时间对比
void TestOp()
{
	srand((unsigned int)time(NULL));
	const int n = 100000;
	int* a1 = (int*)malloc(sizeof(int) * n);
	int* a2 = (int*)malloc(sizeof(int) * n);

	for (int i = 0; i < n; ++i)
	{
		a1[i] = rand();
		a2[i] = a1[i];
	}

	int begin1 = clock();
	InsertSort(a1, n);
	int end1 = clock();

	int begin2 = clock();
	ShellSort(a2, n);
	int end2 = clock();


	printf("InsertSort:%d\n", end1 - begin1);
	printf("ShellSort:%d\n", end2 - begin2);

	free(a1);
	free(a2);
}

int main()
{
	TestOp();
	return 0;
}

我们可以看出希尔排序要比插入排序的效率高出很多,当数据量越大的时候,希尔排序的更占优势。

但是,当数组本身就是有序的,希尔排序就比不过插入排序,因为希尔排序存在预排序,执行了就要花费时间。

6、希尔排序特性总结

举报

相关推荐

0 条评论