只有一重循环的排序——侏儒排序(Gnome Sort)
侏儒排序:从头(i=0)开始遍历元素,如果当前元素比前一个元素大(array[i]>array[i-1]),就把它跟前一个元素互换(Swap(a[i],a[i-1]))并继续检查它(i--),否则检查下一个元素(i++)。当i=length时结束排序。
该排序的神奇之处是只有一重循环,而且代码简单。但是一重循环不代表时间复杂度更小,它的时间复杂度依然是O(n^2),原因就在于代码里的i--起到了和二次循环相同的效果。
优点:
1. 最好情况下时间复杂度低——O(n),一个循环跑下来始终i++,非常顺利。
2. 排序稳定,只交换相邻元素的排序都是稳定的。
3. 额外空间使用少,只需要i(记录进度)和t(交换缓存)。如果比较元素是数字,t都能省掉(不使用临时变量交换两个数字)。
缺点:
效率低。我们对比侏儒排序和直接插入排序。会发现这二者的排序思想一模一样,但是插入排序有2处优化是侏儒排序没做到的:
a. 插入排序遇到不匹配位置的新元素时,把前面的元素挨个后移,然后把新元素直接插入到合适位置(如果位置移动k位,则赋值k+1次)。而侏儒排序是把新元素逐个和前一个元素作交换,一路换位到合适位置,这是典型的冒泡做法(如果位置移动k位,则赋值3*k次)。
b. 当一个元素好不容易从第10位冒泡到第1位的时候,那么此时前10位一定是有序序列。插入排序会直接从第11位继续处理,而侏儒排序只能从第2位继续处理,因为它不知道上个元素是从哪个位置走到第1位的,只好多走冤枉路。
下面是C#代码:
void GnomeSort(List<int> a)
{
int i = 0;
while (i < a.Count)
{
if (i == 0 || a[i - 1] <= a[i])
{
i++;
}
else
{
int t = a[i];
a[i] = a[i - 1];
a[i - 1] = t;
i--;
}
}
}
当然,我们可以通过打补丁的方式来优化它,不过如果这么做了,我们干嘛不直接使用直接插入排序呢?作为直接插入排序的劣质版,它基本上没有实用价值,但是通过研究它,我们就能知道为什么直接插入排序能在这一众O(n^2)排序中脱颖而出了。
只有一重循环的排序——侏儒排序(Gnome Sort)的更多相关文章
- 地精排序(Gnome Sort) 算法
gnome应该是最简单排序的排序算法吧!Gnome Sort,这是该算法的作者命名的,O(n*n)时间复杂度,O(1)空间复杂度,属于稳定的排序算法.算法的思想是每趟循环找到第一个逆序的元素,把它和在 ...
- 数据结构杂谈(二)简单有趣的地精排序Gnome sort
很早之前便听说过地精排序的名字,今天自己看来一下,发现这是一种非常简单而且有趣的排序算法. 为什么叫地精排序? 地精排序在2000年由Dr. Hamid Sarbazi-Azad 提出的时候被称作 s ...
- Hark的数据结构与算法练习之地精(侏儒)排序
算法说明 地精排序是交换排序的一种,它是冒泡排序的一种改良,我感觉和鸡尾酒排序挺像的. 不同之处是鸡尾酒排序是从小到大,然后再从大到小切换着排序的.而地精排序是上来先从小到大排序,碰到交换到再从大到小 ...
- 数组升序排序的方法Arrays.sort();的应用
package com.Summer_0421.cn; import java.util.Arrays; /** * @author Summer * 数组升序排序的方法Arrays.sort();应 ...
- 连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort)
连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort) 1,起泡排序(bubble sort),大致有三种算法 基本版,全扫描. 提前终止版,如果发现前区里没有发生交换 ...
- 排序--选择排序Selection Sort Java实现
基本原理 选择排序的简单原理:选择排序算法通过从未排序部分重复查找最小元素(考虑升序)并将其放在开头来对数组进行排序. 将数组两个子数组: 已排序子数组 未排序子数组 选择排序中每次循环都会从未排序子 ...
- 经典排序算法 – 插入排序Insertion sort
经典排序算法 – 插入排序Insertion sort 插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 插入排序方法分直接插入排序和折半插入排序两种, ...
- 两种应该掌握的排序方法--------1.shell Sort
先了解下什么都有什么排序算法 https://en.wikipedia.org/wiki/Sorting_algorithm http://zh.wikipedia.org/zh/%E6%8E%92% ...
- Python 列表排序方法reverse、sort、sorted详解
python语言中的列表排序方法有三个:reverse反转/倒序排序.sort正序排序.sorted可以获取排序后的列表.在更高级列表排序中,后两中方法还可以加入条件参数进行排序. reverse() ...
随机推荐
- 一个Java方法能使用多少个参数?
我最近给我fork的项目QuickTheories增加了一个接口: @FunctionalInterface public interface QuadFunction<A, B, C, D, ...
- 《JAVA并发编程的艺术》学习笔记
第一章:并发编程的挑战 1.1 上下文切换 即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制.时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通 ...
- 实验08——java百文百鸡
package cn.tedu.demo; /** * @author 赵瑞鑫 E-mail:1922250303@qq.com * @version 1.0 * @创建时间:2020年7月17日 下 ...
- JS 下拉菜单案例
css代码 .nav { width: 300px; height: 400px; list-style: none; padding:; margin: 0 auto; } .nav>li { ...
- vue-cookies 使用
import VueCookies from 'vue-cookies' Vue.use(VueCookies) $cookies.config() 设置默认值 $cookies.config(exp ...
- C#LeetCode刷题-队列
队列篇 # 题名 刷题 通过率 难度 363 矩形区域不超过 K 的最大数值和 27.2% 困难 621 任务调度器 40.9% 中等 622 设计循环队列 C#LeetCode刷题之#622 ...
- C#算法设计排序篇之01-冒泡排序(附带动画演示程序)
冒泡排序(Bubble Sort) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/672 访问. 它重复地访问要排序的元 ...
- DRF内置权限组件之自定义权限管理类
DRF内置权限组件permissions 权限控制可以限制用户对于视图的访问和对于具体数据对象的访问. 在执行视图的dispatch()方法前,会先进行视图访问权限的判断 在通过get_object( ...
- 存储系列之 VFS虚拟文件系统简介
引言:文件系统发展到一定阶段,开始进一步抽象和分层. 前面我们介绍了ext系列文件系统和xfs文件系统,这些是Linux使用最多的文件系统,也是很多发布版本默认选择的文件系统.而事实上,Linux ...
- JS实现call,apply,bind函数
实现之前的预备知识 ...用作展开 ...用作剩余参数 Object.create()的作用 原型链与构造函数 这些有时间补上吧 call函数实现 Function.prototype.myCall ...