数据结构杂谈(二)简单有趣的地精排序Gnome sort

很早之前便听说过地精排序的名字,今天自己看来一下,发现这是一种非常简单而且有趣的排序算法。

为什么叫地精排序?

地精排序在2000年由Dr. Hamid Sarbazi-Azad 提出的时候被称作 stupid sort,可见其思想的简单性。后来,这个算法被Dick Grune 描述成地精排序Gnome sort。

故事背景:

Here is how a garden gnome sorts a line of flower pots.  Basically, he looks at the flower pot next to him and the previous one;  if they are in the right order he steps one pot forward, otherwise he swaps them and steps one pot backwards.  Boundary conditions: if there is no previous pot, he steps forwards; if there is no pot next to him, he is done.
—Dick Grune

大意就是有一个地精(一种荷兰的花园地精 tuinkabouter https://nl.wikipedia.org/wiki/Tuinkabouter在排列一排花盘。他从前至后的排列,如果相邻的两个花盘顺序正确,他向前一步;如果花盘顺序错误,他后退一步,直到所有的花盘的顺序都排列好。

“Gnome sort”的图片搜索结果

这就是萌萌的gnome(tuinkabouter)

算法思想

这个算法可以看作是冒泡排序的简化版。冒泡排序的思想是不断交换反序对,使得最大的元素浮出水面,而地精排序在发现反序对时,把它往回按,直到排好序,再向前继续走。

c++实现

地精排序只需要一重循环,非常简单,也解释了为什么一开始会被叫做stupid。

void gnomeSort(int n, int ar[])
{
    int i = 0;
    while (i < n) 
    {
        if (i == 0 || ar[i - 1] <= ar[i]) 
            i++;
        else 
        {
            int tmp = ar[i]; 
            ar[i] = ar[i - 1];
            ar[--i] = tmp;
        }
    }
}

这里要注意,当i为0时,说明回到了起点,此时需要向前移动。

地精排序的优化

地精在发现反序对时,会用一块石头标记处当前的位置,然后把反序的花盘往回交换。当这个花盘找到了正确的位置之后,地精会瞬间移动回石头标记的位置上。在这种情况下,地精排序成为了一种插入排序。

地精排序的分析

最好情况下,序列是已经排好的,时间复杂度是O(n),最坏情况下,序列式反序的,时间复杂度是O(n^2),与冒泡排序相同。

posted @ 2016-04-17 20:50  marcusxu  阅读(1990)  评论(0编辑  收藏  举报