Gnome排序(地精排序)

Gnome排序(地精排序),起初由Hamid Sarbazi-Azad 於2000年提出,並被稱爲stupid排序,後來被Dick Grune描述並命名爲“地精排序”,作爲一個排序算法,和插入排序類似,除了移動一個元素到最終的位置,是通過交換一系列的元素實現,就像冒泡排序一樣。概念上十分簡單,不需要嵌套循環。時間複雜度爲O(n2),但是如果初始數列基本有序,時間複雜度將降爲O(n)。實際上Gnome算法可以和插入排序算法一樣快。平均運行時間爲O(n2).

Gnome排序算法總是查找最開始逆序的一對相鄰數,並交換位置,基於交換兩元素後將引入一個新的相鄰逆序對,並沒有假定當前位置之後的元素已經有序.

下面gnome排序算法的僞代碼,使用0起始索引數組:

procedure gnomeSort(a[])

    pos := 1

    while pos < length(a)

        if (a[pos] >= a[pos-1])

            pos := pos + 1

        else

            swap a[pos] and a[pos-1]

            if (pos > 1)

                pos := pos - 1

            end if

        end if

    end while

end procedure

實例

給定一個無序數組, a = [5, 3, 2, 4], gnome排序將在while循環中執行如下的步驟.  "current position"採用加粗黑體:

當前數組

操作

[5, 3, 2, 4]

a[pos] < a[pos-1], 交換:

[3, 5, 2, 4]

a[pos] >= a[pos-1],  pos自增:

[3, 5, 2, 4]

a[pos] < a[pos-1], 交換並且pos > 1, pos自減:

[3, 2, 5, 4]

a[pos] < a[pos-1], 交換並且pos <= 1, pos自增:

[2, 3, 5, 4]

a[pos] >= a[pos-1],  pos自增:

[2, 3, 5, 4]

a[pos] < a[pos-1], 交換並且pos > 1, pos自減:

[2, 3, 4, 5]

a[pos] >= a[pos-1], pos自增:

[2, 3, 4, 5]

a[pos] >= a[pos-1], pos自增:

[2, 3, 4, 5]

pos == length(a), 完成.

C代碼如下:

#include<stdio.h>     
#include<stdbool.h>  
void swap(int *a, int *b)   //交換兩元素的值
{
    int t;
    t = *a;
    *a = *b;
    *b = t;
}
void printArray(int a[], int count)   //打印數組元素
{
    int i;
    for(i = 0; i < count; i++)
        printf("%d ",a[i]);
    printf("\n");
}
void gnome_sort(int *a, int len)   //gnome排序算法
{
    int pos = 1;
    while(pos < len) {
        if(a[pos] >= a[pos - 1]) {
            pos++;
        } else {
            swap(&a[pos], &a[pos - 1]);
            if(pos > 1) pos--;
        }
    }
}
int main(void)   
{
    int a[] = {3, 5, 4, 6, 9, 7, 8, 0, 1};
    int n = sizeof(a) / sizeof(*a);
    printArray(a, n);
    gnome_sort(a, n);
    printArray(a, n);    
    return 0;
}


優化:

gnome算法還可以通過引入一個變量,用於存儲每次返回到數組前面的位置來進行優化。採用這樣的優化,gnome排序將成爲一個變種插入排序,下面優化後gnome排序算法的僞代碼,使用0起始索引數組:

procedure optimizedGnomeSort(a[])

    pos := 1

    last := 0

    while pos < length(a)

        if (a[pos] >= a[pos-1])

            if (last != 0)

                pos := last

                last := 0

            end if

            pos := pos + 1

        else

            swap a[pos] and a[pos-1]

            if (pos > 1)

                if (last == 0)

                    last := pos

                end if

                pos := pos - 1

            else

                pos := pos + 1

            end if

        end if

    end while

end procedure

C代碼如下:

#include<stdio.h>     
#include<stdbool.h>  void swap(int *a, int *b)   //交換兩元素的值
{
    int t;
    t = *a;
    *a = *b;
    *b = t;
}
void printArray(int a[], int count)   //打印數組元素
{
    int i;
    for(i = 0; i < count; i++)
        printf("%d ",a[i]);
    printf("\n");
}void optimizedGnome_Sort(int *a, int len)   //優化後的gnome排序
{
    int last, pos;
    last = 0; pos = 1;
    while(pos < len) {
        if(a[pos] >= a[pos - 1]) {
            if(last != 0) {
                pos = last;
                last = 0;
            }
            pos++;
        } else {
            swap(&a[pos], &a[pos - 1]);
            if(pos > 1) {   
                if(last == 0)
                    last = pos;
                pos--;
            } else {
                pos++;
            }
        }
    }
}
int main(void)   
{
    int a[] = {3, 5, 4, 6, 9, 7, 8, 0, 1};
    int n = sizeof(a) / sizeof(*a);
    printArray(a, n);
    optimizedGnome_Sort(a, n);
    printArray(a, n);    
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章