GnomeSort(侏儒排序)——C语言实现

前言:

 

这真是我写过最简单的排序了,比冒泡还简单,小小排序有趣有趣。

这个排序在数组基本有序的情况下,时间复杂度可以达到O(n),确实是厉害的,让我们看看怎么写

思路:

基本上,他看着旁边的花盆和前一个花盆; 如果他们按照正确的顺序,他会向前迈出一个底池,否则他会将它们交换掉,并向后踩一个底池(这是百度百科的解释哈哈哈,我觉得很形象)

就是只考虑两个位置的有序,如果有序,下标前进;如果无序,交换两个的位置,并且下标后退。只需要注意的是由于是比较前一个位置,容易下标越界。

既然思路如此简单,直接上代码:

void GnomeSort(int *a,int length)
{
	int i = 1;
	while (i < length)
	{
		if (a[i] >= a[i - 1] || i <= 0)
			i++;
		else
		{
			swap(&a[i], &a[i - 1]);
			i--;
		}
	}
}

这个算法虽说在最好情况下可以逼近O(n)的时间复杂度,但是在普遍情况下,i的回退其实就相当于第二层的循环,换句话说就是平常的时间复杂度是O(n^2)。而且这是低效的回退,因为每次回退只能回退1,我们当然可以利用一个数组来记录回退的位置(这和KMP算法是不是挺像的),但这样我们为什么不用直接插入排序呢?他有着同样的时间复杂度,并且效率很高。

借用一篇文章中的话:

插入排序遇到不匹配位置的新元素时,把前面的元素挨个后移,然后把新元素直接插入到合适位置(如果位置移动k位,则赋值k+1次)。而侏儒排序是把新元素逐个和前一个元素作交换,一路换位到合适位置,这是典型的冒泡做法(如果位置移动k位,则赋值3*k次)。

原文地址:只有一重循环的排序——侏儒排序(Gnome Sort) - 九德真君 - 博客园 (cnblogs.com)

因此,这个仅仅一重循环的排序算法还是有不少缺陷的,但是这丝毫不妨碍他作为一重循环的排序算法的伟大地位。

我的测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#define N 30

//之前写过了,就不再全写一遍了
void generate_random_number(int*, int, int);
void swap(int*, int*);

void GnomeSort(int *a,int length)
{
	int i = 1;
	while (i < length)
	{
		if (a[i] >= a[i - 1] || i <= 0)
			i++;
		else
		{
			swap(&a[i], &a[i - 1]);
			i--;
		}
	}
}

int main()
{
	int arr[N + 10] = { 0 };
	generate_random_number(arr, 0, 1024);

	GnomeSort(arr,N);

	printf("排序后数列:\n");
	for (int i = 0; i < N; i++)
		printf("%d ", arr[i]);

	printf("\n");
	return 0;
}

测试结果:

至此,GnomeSort(侏儒排序)完成。

你可能感兴趣的:(排序算法,C语言,排序算法,c语言)