插入排序

排序算法--插入排序

此生再无相见时 提交于 2019-11-27 14:14:29
继续备忘一个简单的排序算法--插入排序,并且仍旧对整数组成的数组进行升序排序。 原理: 同样基于元素比较进行排序。进行第N趟遍历的时候,前面N-1个元素已经有序,只需要从右向左逐个和已经排好序的元素比较,去寻找第N个元素可以插入的位置,找到之后插入即可。遍历N-1趟。 步骤: 初始化遍历指针i,j。i代表每次需要拿去插入的元素的下标,j遍历已经排过序的部分,找到应该插入的位置插入。直到i代表将所有元素都插入到应该插入的位置了。 分析: 时间复杂度方面,需要遍历n次,最好情况是已经升序排好,此时不需要移动元素,最坏的也就是逆序的时候,需要移动n(n-1)/2次,平均时间复杂度为O(n^2)。它也是原地排序。稳定性方面,因为每次插入的时候,只有前面的元素大于被插入元素才进行后移,所以是稳定的。 代码展示 : public class InsertSort { public static void main(String[] args){ int[] array = {7, 11, 5, 8, 7, 2, 10, 1}; System.out.print("待排序数组:");//打印排序之前的样子 for(int k : array) System.out.print(k + " "); System.out.println(); sort(array);//排序之中 System

经典排序算法--java实现

情到浓时终转凉″ 提交于 2019-11-27 14:10:47
经典排序算法--java实现 概述 算法的性能指标 时间复杂度 空间复杂度 稳定性 简单的桶排序 原理分析 代码实现 性能分析 经典的冒泡排序 原理分析 代码实现 性能分析 性能最好的快速排序 原理分析 代码实现 性能分析 换一种思路—插入排序 原理分析 代码实现 性能分析 插入排序的优化版—shell排序 原理分析 代码实现 性能分析 概述 排序算法是计算机算法里的基础概念,也是很多大厂面试的必考内容。不管你是应届毕业的小鲜肉还是浸淫技术多年的老司机,都免不了会和排序打交道。正因为大部分小伙伴平日的学习和工作中直接接触算法的几率并不大,所以时间久了以后难免生疏。正因为忘的差不多了,所以有必要把一些经典排序算法的思想和实现思路再温习一下。所谓温故而知新,总会有新的收获。 本文涉及的主要知识点: 算法的性能指标 简单的桶排序 经典的冒泡排序 性能最好的快速排序 换一种思路—插入排序 插入排序的优化版—shell排序 算法的性能指标 时间复杂度 时间复杂度是一个函数,使用O表示,一般情况下,时间复杂度由高到低的顺序是O(n 2 )>O(nlogn)>O(n)>O(logn)>O(1)。 一般如果一种算法的时间复杂度高于O(n2),那么就需要考虑是否可以寻找更优化的方案,在代码层面,一般是以循环的嵌套层次来辨别算法的时间复杂度。 比如两层循环嵌套,那么每层循环都需要执行n次,一共是n 2

排序算法 - 插入排序

泄露秘密 提交于 2019-11-27 10:53:18
直接插入排序 基本思路 一趟直接插入排序:在有序区中插入R [i]的过程。 算法代码 1 //直接插入排序 2 void InsertSort(int *arr, int n) 3 { 4 int i, j; 5 int temp; 6 7 for (i = 1; i < n; i++) 8 { 9 if (arr[i] < arr[i - 1]) //如果第i个和前面的已排序的最后一个元素反序时,才开始移动 10 { 11 temp = arr[i]; //记住这个元素 12 for (j = i - 1; j >= 0 && arr[j] > temp; j--) 13 { 14 arr[j + 1] = arr[j]; //将比temp大的元素统一向后移动 15 } 16 arr[j + 1] = temp; //在条件不满足之前j--了一次,在j+1处放入temp 17 } 18 } 19 } 算法分析 折半插入排序 基本思路 直接插入排序,当有序区元素太多时,在有序区中寻找插入位置可能比较的次数太多,采用折半插入法,即折半查找到要插入的位置,加快了查找效率,但是要移动的元素仍然和直接插入排序的相同,仅仅提升了查找效率。 算法代码 1 //折半插入排序 2 void BinInsertSort(int *arr, int n) 3 { 4 int i, j; 5 int

排序算法之——插入排序

二次信任 提交于 2019-11-27 08:26:11
插入排序思想: 将插入的元素记录,与前面的元素进行比较大小,查询到插入的位置,然后再将比它大的元素向后面移动,空出插入的位置,将元素插入。 剩下的和②步骤一样。。。 代码这里给出了3种,从基础到优化 //1 void InsertSort(int* a, int n) { for (int i = 1; i < n; ++i) { if (a[i] < a[i - 1]) { int temp = a[i]; for (int j = 0; j < i; ++j) { if (temp < a[j]) { for (int k = i; k > j; k--) a[k] = a[k - 1]; a[j] = temp; break; } } } } } //2 void InsertSort(int* a, int n) { int i, j; for ( i = 1; i < n; i++) { if (a[i] < a[i - 1]) { int temp = a[i]; for (j = i; j >= 0 && a[j-1] > temp; j--) { a[j] = a[j - 1]; } a[j] = temp; } } } //3void InsertSort(int* a, int n) { int temp; for (int i = 1; i < n; i++)

插入排序

走远了吗. 提交于 2019-11-27 07:09:10
1、什么是插入排序?   一组未经排序的序列,从前向后依次放入一个有序的序列,每次插入时从已排序序列的最后向前比较,找到相应的位置插入。 2、插入排序非常类似于整扑克牌。   在开始摸牌时,左手是空的,牌面朝下放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左地进行比较。无论什么时候,左手中的牌都是排好序的。 3、时间复杂度和空间复杂度   空间复杂度为 :O(1)   时间复杂度     最差情况:反序,需要移动n*(n-1)/2次元素 O(n^2)     最好情况:正序,不需要移动元素 数组在已排序或者是“近似排序”时,插入排序效率的最好情况运行时间为O(n);     平均情况:O(n^2)   对于具有较少元素(如n<=15)的列表来说,二次算法十分有效。 4、算法描述   一个长度为n的数组,假定第一个元素(下标为0)已经排好序,算法从数组的第2个元素(下标为1)开始,   每次从后向前遍历已经排好序的数组,   将插入值赋值给一个临时变量,然后进行比较   如果小于前一个元素,则将前一个元素后移(此时插入值原来的位置会被覆盖)   找到正确的位置或已经到了数组第一个位置时,将临时变量的值插入进来完成排序 5、代码示例 class InsertSort { public static

冒泡排序 快速排序 插入排序 选择排序——java语言简单实现

荒凉一梦 提交于 2019-11-27 05:42:22
目录 1.冒泡排序: 2.快速排序: 3.插入排序: 4.选择排序: 1.冒泡排序: 冒泡排序重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。 这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。 /** * 冒泡排序: * 1.比较相邻的元素。如果第一个比第二个大,就交换它们两个; * 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数; * 3.针对所有的元素重复以上的步骤,除了最后一个; * 4.重复步骤1~3,直到排序完成。 */ public class BubbleSort { public static void outA(int [] a){ for (int i : a) { System.out.print(" "+i); } System.out.println(); } public static void main(String[] args) { int [] a = new int[]{2, 5, 6, 8, 9, 1, 3, 4, 7,0}; int

前端十大算法

一曲冷凌霜 提交于 2019-11-27 05:35:45
排序算法说明 (1)排序的定义:对一序列对象根据某个关键字进行排序; 输入:n个数:a1,a2,a3,…,an 输出:n个数的排列:a1’,a2’,a3’,…,an’,使得a1’ 再讲的形象点就是排排坐,调座位,高的站在后面,矮的站在前面咯。 (3)对于评述算法优劣术语的说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面; 不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面; 内排序:所有排序操作都在内存中完成; 外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行; 时间复杂度: 一个算法执行所耗费的时间。 空间复杂度: 运行完一个程序所需内存的大小。 关于时间空间复杂度的更多了解请戳这里,或是看书程杰大大编写的《大话数据结构》还是很赞的,通俗易懂。 (4)排序算法图片总结(图片来源于网络): 排序对比: 这里写图片描述 图片名词解释: n: 数据规模 k:“桶”的个数 In-place: 占用常数内存,不占用额外内存 Out-place: 占用额外内存 排序分类: 这里写图片描述 1.冒泡排序(Bubble Sort) 好的,开始总结第一个排序算法,冒泡排序。我想对于它每个学过C语言的都会了解的吧,这可能是很多人接触的第一个排序算法。 (1)算法描述 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列

希尔排序

China☆狼群 提交于 2019-11-27 04:39:16
算法思想 希尔排序算法思想 使用一个增量序列{t1,t2,t3,......tn},其中tn>....>t2>t1=1,其实这个增量序列也可以理解为 间距序列; 设有数组A[k],下标从0开始: 当增量为tn时,从数组首元素A[0]开始,此时距离首元素间隔为tn的元素是A[tn],下一个距离元素A[tn] 间隔为tn的元素是A[tn*2],依次类推,从首元素开始间隔为tn的所有元素,A[0],A[tn],A[2*tn].... A[x*tn]构成了一个分组,其中x*tn<k; 从数组第二个元素A[1]开始,此时距离A[1]间隔为tn的元素是 A[1+tn],下一个距离元素A[1+tn]间隔为tn的元素是A[1+tn*2],依次类推,从首元素开始间隔为tn的所 有元素,A[1],A[1+tn],A[1+2*tn]....A[1+x*tn]构成了一个分组,其中1+x*tn<k; 重复上述步骤,数组中所有的元素都被分组后,然后对每一个分组进行一次插入排序 取增量为tn-1,重复上述步骤进行分组,然后对每一个分组进行一次插入排序,直到取增量为t1时,此时数 组中的元素大致有序,在对整个数组进行一次插入排序,即可排序完成 算法图解 使用希尔排序对4,5,8,2,3,9,7,1进行排序,此时采用增量序列为{1,2,3}, 当增量为3时: 当增量为2时: 当增量为1时: 可以看出当增量为1时

python实现希尔排序

假装没事ソ 提交于 2019-11-27 02:42:27
python实现希尔排序 希尔排序: 实现分析: 实际上希尔排序就是对插入排序的一种改进而已, 希尔排序是将整个列表当成一个无序序列,并将其分成多个无序序列来进行插入排序,而实现分成多个序列就是需要一个gap步长来实现,对于普通的插入排序gap就是等于1。 我们还是以 __[54,26,93,17,77,31,44,55,20]__为例子。为了分析,我们假设gap先等于2, 图一是我们未划分之前的列表,图二是根据gap划分而来的两个列表,我们需要对每一个列表进行插入排序,排序玩以后得到如下的图 此时步长为2时已经排序完成,现在我们就需要减小步长为1再次进行排序,这时就与普通的插入排序一样了,笔者就不再多说,对于插入排序,可以参考链接: 普通的插入排序实现 . (1)首先我们先把插入排序比较的框架写出来 while i>0: if alist[i]<alist[i-1]: alist[i],alist[i-1]=alist[i-1],alist[i] i-=1 else: break 但是对于希尔排序来说比较的不再是前一个元素,而是以步长来比较的元素,所以这里的1需要改成gap。 (2)对于(1)来说我们仅仅实现了第一步,对于一次进行的排序,而对于一整个序列来说我们需要比较多次,所以我们需要用到一个for循环 for j in range(gap,n ): i=j

插入排序

喜欢而已 提交于 2019-11-27 01:23:36
1、思路:假定前面的序列已经有序,当前元素插入前面有序的序列。从后往前遍历,比当前元素大的,往后移,为当前元素腾出位置。 2、代码: 1 template <typename T> 2 void InsertSort(vector<T>& vec) 3 { 4 for ( int i= 1 ; i< vec.size();i++ ) 5 { 6 int j = i; 7 T target = vec[i]; 8 while (j> 0 && target<vec[j- 1 ]) 9 { 10 vec[j] = vec[j- 1 ]; 11 j-- ; 12 } 13 if (j!= i) 14 { 15 vec[j] = target; 16 } 17 } 18 } 3、上面代码有个问题,当前元素找自己位置的时候,从后往前遍历,既然前面的序列已经有序,可以采用二分查找。代码: 1 template <typename T> 2 int FindPosition( const vector<T>& vec, int lhs, int rhs,T target) 3 { 4 if (rhs-lhs == 1 ) 5 { 6 if (target> vec[lhs]) 7 { 8 return rhs; 9 } 10 else 11 { 12 return lhs; 13 } 14 }