插入排序

插入排序

白昼怎懂夜的黑 提交于 2019-12-04 06:12:30
插入排序好似我们打扑克牌时放牌一样, 假如有这样一个数组: 把数组分成两个部分,已排序区和未排序区,假如我们认为第一个数已排序 将 来源: https://www.cnblogs.com/zqr99/p/11835684.html

【排序算法】(3)插入排序

痴心易碎 提交于 2019-12-04 04:17:34
插入排序 2019-11-10 11:40:40 by冲冲 1、概念 直接插入排序(Straight Insertion Sort),把n个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。 2、基本思想 假设{20,30,40,10,60,50}中的前3个数已经排列过,是有序的了,接下来对10进行排列。图中将数列分为有序区和无序区。我们需要做的工作只有两个:(1)取出无序区中的第1个数,并找出它在有序区对应的位置。(2)将无序区的数据插入到有序区,若有必要的话,则对有序区中的相关数据进行移位。 3、完整代码 1 public class InsertSort { 2 /** 参数说明: 3 * a -- 待排序的数组 4 * n -- 数组的长度 5 */ 6 public static void insertSort(int[] a, int n) { 7 int i, j, k; 8 for (i = 1; i < n; i++) { 9 //为a[i]在前面的a[0...i-1]有序区间中找一个合适的位置 10 for (j = i - 1; j >= 0; j--) 11 if (a[j] < a[i])

【排序算法】(8)希尔排序

笑着哭i 提交于 2019-12-04 04:15:19
希尔排序 2019-11-10 11:44:39 by冲冲 1、概念 希尔排序(shell排序),是插入排序(直接插入)的增强版。 特点是,在不断缩小增量的过程中,不断地排序,使得在最终使用插入排序时,序列已经基本有序。插入排序在操作基本有序的序列时效率倍增。 2、基本思想 把序列按步长gap分组,对每组小序列采用直接插入排序方法进行排序。 随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小到1时,整个数据合成为一组,构成一组基本有序的序列,进行最后一趟插入排序,完成排序。 例析, 初始时,有一个大小为 10 的无序序列。 在第一趟排序中,设置 gap1 = N / 2 = 5,即相隔距离为 5 的元素组成一组,可以分为 5 组。然后使用直接插入排序的方法对每个组进行排序。 在第二趟排序中,设置 gap2 = gap1 / 2 = 2 (取整数)。即每相隔距离为 2 的元素组成一组,可以分为 2 组。然后使用直接插入排序的方法对每个组进行排序。 在第三趟排序中,设置gap3 = gap2 / 2 = 1。 即相隔距离为 1 的元素组成一组,即只有一组。然后使用直接插入排序的方法对每个组进行排序。此时,排序已经结束。 希尔排序是不稳定性排序:图中有两个相等数值的元素 5 和 5,在排序过程中,两个元素位置交换了。 3、完整代码 1 public class

数据结构学习--Java希尔排序

你说的曾经没有我的故事 提交于 2019-12-03 20:21:08
插入排序的缺陷 多次移动。假如很小的数据在靠右端的位置上,那么要将该数据排列到正确的位置上,则所有的中间数据都需要向右移动一位。 特别是如果数据量大,但是某些较小的数据排在了最后面,那么移动位置将非常消耗时间。 希尔排序的优点 通过加大插入排序中元素之间的间隔,并对这些间隔的元素进行插入排序,从而使得数据可以大幅度的移动,当完成该间隔的排序后, 希尔排序会减少数据的间隔进行排序,依次进行下去。 间隔计算 间隔h的初始值为1,通过h = 3*h + 1来计算循环,直到该间隔大于数组的大小时停止。最大值间隔为不大于数组大小的最大值。 间隔的减少 h = (h -1)/3 第三趟排序使用插入排序即可。 代码实现: package com.example.deer;public class ShellSort { public void sort(long[] arr){ //初始化一个间隔 int h = 1; //计算最大间隔 while(h < arr.length / 3){ h = h * 3 + 1; } while (h > 0){ //进行插入排序 long tmp = 0; for(int i = h;i < arr.length;i ++){ tmp = arr[i]; int j = i; while (j > h - 1 && arr[j - h] >= tmp){

【算法】小规模排序

淺唱寂寞╮ 提交于 2019-12-03 18:16:22
在将排序之前,首先思考一个问题:选择排序、插入排序、冒泡排序的时间复杂度均为 o(n) ,为什么大家在讲排序的时候首先更愿意讲插入排序? 在分析一个排序算法好坏的时候,往往要考虑这么几个方面: 1.时间复杂度 考虑到时间复杂度的时候就要考虑到最好情况和最坏情况,尽可能多的有序当然是最好的情况,完全逆序则是最坏的情况,有序度不同,算法的性能也不同。 2.空间复杂度 算法的内存消耗可以通过空间复杂度来衡量。其中,原地排序算法,指的是空间复杂度 o(1)的算法。 3.排序算法的稳定性 稳定性指的是,如果待排序的序列中存在值相等的元素,经过排序以后,相等元素之间原有的先后顺序不变。 举个例子,如果现在我们要给电商交易系统的“订单”排序,订单有俩个属性,一个是下单时间,一个是订单金额。对于时间相同的订单,我们希望按照金额从小到大排序,对于金额相同的订单,我们希望按照下单时间从早到晚排序。那么我们可以按照俩个属性分别排一次续,如果是稳定的排序算法,假设第一次按时间排序,第二次按照金额排序,那么稳定算法可以保持金额相同的俩个对象,在排序后的前后顺序不变。 首先介绍一下三种排序算法: 冒泡排序 冒泡排序只会操作俩个相邻的数据,每次冒泡操作都会对相邻的俩个元素进行比较,如果不满足大小关系要求就让它俩互换。一次有效的冒泡至少会让一个元素移动到它应该在的位置,重复N次就完成了N个数据的排序工作。 实际上

对链表进行插入排序

 ̄綄美尐妖づ 提交于 2019-12-03 17:20:19
对链表进行插入排序。 插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。 插入排序算法: 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。 重复直到所有输入数据插入完为止。 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 解法1: public static ListNode insertionSortList2(ListNode head) { /*定义一个哑节点*/ ListNode dumb = new ListNode(0); /*哑节点的下一个指向head*/ dumb.next = head; /*定义一个当前节点指针*/ ListNode cur = head; /*当当前节点和它的下一个节点不为null时继续循环*/ while (cur != null && cur.next != null) { /*依次把当前节点与它的下一个节点进行对比,如果当前节点的值比当前节点的下一个节点的值小,则当前节点向后移动一位,否则进行下一步*/ if (cur.val < cur.next.val) { cur

数据结构与算法——常用排序算法及其Java实现

邮差的信 提交于 2019-12-03 14:01:51
冒泡排序 原理: 依次比较相邻的两个数,将小数放在前面(左边),大数放在后面(右边),就像 冒泡 一样 具体操作: 第一趟,首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后,这样第一趟下来最大的数就在最后一位了。然后还是从第一个数开始重复第一趟步骤比较,但是这次不比较最后一个数了,第二趟结束后第二大的数就在倒数第二位......以此类推,直至全部排序完成。 所有代码 在这 ,关键代码如下: private static void sort(Comparable[] a) throws IllegalAccessException, InstantiationException { Object tmp; boolean noChange = false;//用来标识输入序列的排序情况, for (int i = 0;i<a.length-1 && !noChange;i++){ noChange = true;//如果某一趟没有交换,说明数据已经排好序无需再进行接下来的排序 for (int j=0;j<a.length-1-i;j++){ if(a[j].compareTo(a[j+1])>0){ tmp = a[j]; a[j] = a[j+1]; a[j+1] =

算法的好坏是如何分析的?

情到浓时终转凉″ 提交于 2019-12-03 13:32:21
前言 本文以插入排序为例,结合自身学习过程中遇到的问题,介绍如何分析算法的复杂度, 因为掌握此方法后,就可以对遇到的任何算法做一个形式化的评估,从而了解算法的执行效率。 本文先给出计算插入排序算法运行时间的表示方式和计算方法,再给出其最好情况、最坏情况的分析过程,最后引出 Θ \Theta Θ (读作theta)表示。相信看完本文后,就可以更清楚的明白:时间复杂度、 Θ \Theta Θ 、大 O O O 等曾经困惑过你的概念。 具体插入排序的算法的思想请见之前的博文《 插入排序 》,或者可参考《算法导论》 P 9 P_9 P 9 ​ ~ P 12 P_{12} P 1 2 ​ ,这里假设读者已经明白了插入排序的算法思路。 算法分析 算法的 运行时间 是指在特定输入时,所执行的基本操作数(或步数)。这里的基本操作数可这么理解,每执行一行 伪代码 (如下图为本文使用的伪代码)都要花一定量的时间,一般情况下各行执行时间是不同的,但这里假设每次执行第 i i i 行所花的时间都是常量 c i c_i c i ​ 。 一般情况下,做简要分析的时候肯定知道,两层循环对于 n n n 个数排序,最坏情况大致为 n 2 n^2 n 2 ,因为想当然的 n ∗ n n*n n ∗ n 嘛!但实际上如果不深入学习里面知识,很多细节未掌握,那么理解的就不深,掌握的就不扎实。 此次分析就是要精细化分析

《数据结构与面向对象程序设计》第8周学习总结

依然范特西╮ 提交于 2019-12-03 11:32:20
学号20182329 2019-2020-1 《数据结构与面向对象程序设计》第8周学习总结 教材学习内容总结 用链表实现队列,以及队列的出入、删除、交换等等操作。 用数组实现队列,同样实现上述操作。 学习查找的ASL算法,对比出更加高效的算法,同时学会鉴别算法的稳定性。 学会最简单的线性查找,以及二分法查找。 学会在查找的基础上进行简单排排序,学会并实现选择排序。 插入排序是将元素插入已有列表。 学习冒泡排序,但是冒泡是一种算法非常复杂的。 学习快速排序和归并排序。 教材学习中的问题和解决过程啊 问题1:在学习归并查找的过程中,发现在分解和归并的每一步中度需要进行一轮比较,也就是说,在一个循环中套两个循环,但是这样的运算算法就会非常复杂,而且只是设置分解在循环中可以,但是很难把合成也放在其中。 问题1解决方法:算法本身复杂是没有解决的方法,两个循环无法并行时,可以将归并部分的代码重新设置一个方法,需要的时候调用就可以了。 问题2:在学习Android 的课程时,不是很理解和使用监听器,自己编写的监听器总是无法连接。 问题2解决方案:在实验2的学习编写中,监听器与按钮相结合的方式,连接两个活动,这当然含有点击、长按等,关键在一个监听器等待一个活动开始后,相应另一个活动,接口是必要且关键的。 问题3:我在编写书上SortPlayerList代码时,发现我设置一个inset(void

20182332 2019-2020-1 《数据结构与面向对象程序设计》第八周学习总结

孤街醉人 提交于 2019-12-03 11:31:36
20182332 2019-2020-1 《数据结构与面向对象程序设计》第八周学习总结 教材学习内容总结 查找: 顺序查找: 顺序查找就是按顺序从头到尾依次往下查找,找到数据,则提前结束查找,找不到便一直查找下去,直到数据最后一位。适用于线性表的顺序存储结构和链式存储结构。 缺点:查找效率低。 二分查找: 将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半。 优点:高效。明显减少比较次数,提高查找效率 缺点:折半查找的先决条件是查找表中的数据元素必须有序。 哈希值查找: 若关键字为k,则其值存放在f(k)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数,按这个思想建立的表为散列表。 冲突:两个不同关键字对应同一个内存地址 开放地址法:线性探测再散列,若关键字对应地址非空,向后移位直到找到空地址存入,查找步骤与之相同。 链地址法:将存储空间定义为链表数组,每一个存储空间都代表一个链表的表头,若出现冲突,直接延长链表的长度,查找顺序与存入顺序相同。 排序: 排序衡量标准:相同元素排序后先后次序是否发生变化 插入排序:利用双重循环和插入,逐渐将整个表从前向后实现有序排列。 折半插入排序:对插入排序的改良