🌻算法,不如说它是一种思考方式🍀
算法专栏: 👉🏻123
插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序包括
直接插入排序和希尔排序
最后排序过元素的索引 到 0 的遍历:{当前元素 j > X:
为了更好的学习排序算法和了解ChatGPT,就让ChatGPT来教我学习插入排序算法吧:
插入排序和希尔排序插入排序是一种简单的排序算法,它通过构建有序序列,对于未排序的数据,在已排序序列中从后向前扫描,找到相应位置并插入。
具体操作是每次将一个待排序的元素插入到已经有序的元素集合中,并保持有序集合的有序性。对于一个长度为n的数组,我们可以先定义一个有序的集合只有第一个元素,然后一次将后面的元素插入到这个集合中,直到所有元素都被插入完成。
希尔排序是插入排序的一种改进版。它通过将一系列间隔较大的待排序元素进行插入排序,使得原来序列中的大部分元素已经基本有序,然后逐渐缩小间隔进行插入排序,最终达到整个序列有序。
具体操作是选择一个增量序列,将数据按增量序列划分成若干子序列,对每个子序列进行插入排序,然后逐步缩小增量,重复以上步骤,直到增量为1。与插入排序相比,希尔排序的关键在于选择合适的增量序列。常用的增量序列有希尔增量、Hibbard增量、Sedgewick增量等。
当数据量不大时,插入排序是一种高效的排序方法,时间复杂度为O(n²),若数据已经有序,则时间复杂度将会变成O(n)。插入排序主要分为直接插入排序和折半插入排序两种。
直接插入排序的基本思想是,将待排序序列分成有序区和无序区。每次从无序区中取出元素,向有序区中插入,直到无序区为空。具体操作为从第二个元素开始,依次将其与前面的有序区进行比较并插入到正确位置上。
折半插入排序是在直接插入排序的基础上,利用二分查找确定插入位置,进一步优化了算法。具体操作是在有序区中找到中间位置后进行比较,如果被排序元素小于中间位置的值,则在左侧有序区递归查找;如果被排序元素大于中间位置的值,则在右侧有序区递归查找。
而希尔排序是对插入排序的一种改进方法,通过将数据分组,对每个分组进行插入排序,使得每次插入可以同时将多个数据进行移动,提高了插入排序的效率。具体而言,希尔排序先将待排序的序列分成若干大小相同的子序列,对每个子序列进行插入排序,然后逐步缩小子序列的长度,直到子序列长度为1,即完成排序。希尔排序的时间复杂度约为O(n^(1.3)),相对于直接插入排序能更快地将数据变成有序状态。
希尔排序的具体实现步骤如下:
下面用一个例子来说明希尔排序的具体过程。
假设有一个无序序列:{10,8,6,20,4,3,22,1,0},选择步长序列为{4,2,1},按照上述步骤进行排序。
步长为4时(将序列分成4组):
第一次分组:{10,4},{8,3},{6,22},{20,1},{4,0}
对每组进行插入排序:
{4,10},{3,8},{6,22},{1,20},{0,4}
对整个序列进行一次插入排序:
{0,3,4,6,1,8,10,20,4},序列变为:{0,3,4,4,6,8,10,20,22}
步长为2时(将序列分成2组):
第一次分组:{0,4,6,10,22},{3,4,8,20}
对每组进行插入排序:
{0,4,6,10,22},{3,4,8,20}
对整个序列进行一次插入排序:
{0,3,4,4,6,8,10,20,22}
步长为1时(将序列分成1组):
对整个序列进行插入排序:
{0,3,4,4,6,8,10,20,22}
最终得到有序序列。
可以通过以下两种方法进一步优化插入排序算法:
二分查找:在插入排序时,可以利用二分查找法快速定位插入位置,避免从头开始逐个比较的方法。具体而言,插入时在有序序列中查找待插入元素的插入位置,从而减少比较次数。
希尔增量:在进行插入排序时,我们可以先将待排序元素分成若干个子序列,对每个子序列进行插入排序,然后再逐步缩小子序列的长度,直到子序列长度为1。希尔排序中的增量序列可以影响排序的效率,而希尔增量序列已知是性能较优的增量序列之一。希尔增量序列的计算方法是:H(n+1) = 2 * H(n) + 1,其中H(1) = 1,n为增量序列的索引。
通过以上两种优化方法,插入排序的时间复杂度可以进一步降低,算法效率更高。
end.
直接插入排序:
public class c0_insert {
public static void main(String[] args) {
int[] arr={10,8,6,20,4,3,22,1,0};
arr=insertionSort(arr);
for (int i : arr) {
System.out.print(" "+i);
}
}
public static int[] insertionSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int preIndex = i - 1;
int current = arr[i];
while (preIndex >= 0 && current < arr[preIndex]) {
arr[preIndex + 1] = arr[preIndex];
preIndex -= 1;
}
arr[preIndex + 1] = current;
}
return arr;
}
}

希尔排序:
public class c1_insert {
public static void main(String[] args) {
int[] arr={10,8,6,20,4,3,22,1,0};
arr=shellSort(arr);
for (int i : arr) {
System.out.print(" "+i);
}
}
public static int[] shellSort(int[] arr) {
int n = arr.length;
int gap = n / 2;
while (gap > 0) {
for (int i = gap; i < n; i++) {
int current = arr[i];
int preIndex = i - gap;
// Insertion sort
while (preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex + gap] = arr[preIndex];
preIndex -= gap;
}
arr[preIndex + gap] = current;
}
gap /= 2;
}
return arr;
}
}
插入排序的时间复杂度为O(n2),空间复杂度为O(1)。
希尔排序的时间复杂度与所选的增量序列有关,平均时间复杂度为O(nlogn)到O(n2)之间,常数因子较小,性能较好。空间复杂度为O(1)。
☕物有本末,事有终始,知所先后。🍭
🍎☝☝☝☝☝我的CSDN☝☝☝☝☝☝🍓
英文版英文链接关注公众号在“亚特兰蒂斯的回声”中踏上一段难忘的冒险之旅,深入未知的海洋深处。足智多谋的考古学家AriaSeaborne偶然发现了一件古代神器,揭示了一张通往失落之城亚特兰蒂斯的隐藏地图。在她神秘的导师内森·兰登教授的指导和勇敢的冒险家亚历克斯·默瑟的帮助下,阿丽亚开始了一段危险的旅程,以揭开这座传说中城市的真相。他们的冒险之旅带领他们穿越险恶的大海、神秘的岛屿和充满陷阱和谜语的致命迷宫。随着Aria潜在的魔法能力的觉醒,她被睿智勇敢的QueenNeria的幻象所指引,她让她为即将到来的挑战做好准备。三人组揭开亚特兰蒂斯令人惊叹的隐藏文明,并了解到邪恶的巫师马拉卡勋爵试图利用其古
我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night
我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195
我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我
我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排
我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果
在我的用户模型中,我有一堆属性,例如is_foos_admin和is_bars_admin,它们决定允许用户编辑哪些类型的记录。我想干掉我的编辑链接,目前看起来像这样:'edit'ifcurrent_user.is_foos_admin?%>...'edit'ifcurrent_user.is_bars_admin?%>我想做一个帮助程序,让我传入一个foo或bar并返回一个链接来编辑它,就像这样:助手可能看起来像这样(这不起作用):defedit_link_for(thing)ifcurrent_user.is_things_admin?link_to'Edit',edit_poly
我有一个对象如下:[{:id=>2,:fname=>"Ron",:lname=>"XXXXX",:photo=>"XXX"},{:id=>3,:fname=>"Dain",:lname=>"XXXX",:photo=>"XXXXXXX"},{:id=>1,:fname=>"Bob",:lname=>"XXXXXX",:photo=>"XXXX"}]我想按fname排序,不区分大小写,所以它会导致编号:1,3,2我该如何排序?我正在尝试:@people.sort!{|x,y|y[:fname]x[:fname]}但这没有任何效果。 最佳答案
有人可以告诉我如何根据自定义字符串对嵌套数组进行排序吗?比如有没有办法排序:[['Red','Blue'],['Green','Orange'],['Purple','Yellow']]“橙色”、“黄色”,然后是“蓝色”?最终结果如下所示:[['Green','Orange'],['Purple','Yellow'],['Red','Blue']]它不是按字母顺序排序的。我很想知道我是否可以定义要排序的值以实现上述目标。 最佳答案 sort_by对于这种排序总是非常方便:a=[['Red','Blue'],['Green','Ora