希尔排序

数据结构之排序基础知识笔记

北战南征 提交于 2020-01-18 22:14:17
概述 最近在温习数据结构,现在针对排序算法写一篇随笔,其中附带原理说明和代码。 插入排序 直接插入排序(Straight Insertion Sort)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次 从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。 假设{20,30,40,10,60,50}中的前3个数已经排列过,是有序的了;接下来对10进行排列。示意图如下: 图中将数列分为有序区和无序区。我们需要做的工作只有两个:(1)取出无序区中的第1个数,并找出它在有序区对应的位置。(2)将无序区的数据插入到有序区;若有必要的话,则对有序区中的相关数据进行移位。 时间复杂度和稳定性 直接插入排序的时间复杂度是O(N2)。 假设被排序的数列中有N个数。遍历一趟的时间复杂度是O(N),需要遍历多少次呢?N-1!因此,直接插入排序的时间复杂度是O(N*N)。 直接插入排序是稳定的算法,它满足稳定算法的定义。 算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的。 插入排序JAVA实现 1 import static javaTest.SortUtils

【数据结构22】希尔排序

梦想与她 提交于 2020-01-18 08:17:38
1. 希尔排序介绍 2. 希尔排序思路 3. 代码实现 3.1 交换法 希尔排序推导过程: public class ShellSort { public static void main ( String [ ] args ) { int [ ] arr = { 8 , 9 , 1 , 7 , 2 , 3 , 5 , 4 , 6 , 0 } ; System . out . println ( "排序前:" + Arrays . toString ( arr ) ) ; shellSort ( arr ) ; } public static void shellSort ( int [ ] arr ) { int temp = 0 ; //第一轮排序:将10个数据分成5组 for ( int i = 5 ; i < arr . length ; i ++ ) { //如果当前元素大于步长后面的那个元素,说明交换 for ( int j = i - 5 ; j >= 0 ; j -= 5 ) { if ( arr [ j ] > arr [ j + 5 ] ) { temp = arr [ j ] ; arr [ j ] = arr [ j + 5 ] ; arr [ j + 5 ] = temp ; } } } System . out . println ( "第1轮:" )

常用的十大排序算法,经典图解版,『精』!!!

倾然丶 夕夏残阳落幕 提交于 2020-01-16 08:33:26
前言 本文或许是东半球分析十大排序算法最好的一篇文章,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程。 预计阅读时间 47 分钟,强烈建议先收藏然后通过电脑端进行阅读。 No.1 冒泡排序 冒泡排序无疑是最为出名的排序算法之一,从序列的一端开始往另一端冒泡(你可以从左往右冒泡,也可以从右往左冒泡,看心情),依次比较相邻的两个数的大小(到底是比大还是比小也看你心情)。 冒泡排序动图演示 图解冒泡排序 以 [ 8,2,5,9,7 ] 这组数字来做示例,上图来战: 从左往右依次冒泡,将小的往右移动 冒泡排序1 首先比较第一个数和第二个数的大小,我们发现 2 比 8 要小,那么保持原位,不做改动。位置还是 8,2,5,9,7 。 指针往右移动一格,接着比较: 冒泡排序2 比较第二个数和第三个数的大小,发现 2 比 5 要小,所以位置交换,交换后数组更新为:[ 8,5,2,9,7 ]。 指针再往右移动一格,继续比较: 冒泡排序3 比较第三个数和第四个数的大小,发现 2 比 9 要小,所以位置交换,交换后数组更新为:[ 8,5,9,2,7 ] 同样,指针再往右移动,继续比较: 冒泡排序4 比较第 4 个数和第 5 个数的大小,发现 2 比 7 要小,所以位置交换,交换后数组更新为:[ 8,5,9,7,2 ] 下一步,指针再往右移动,发现已经到底了,则本轮冒泡结束,处于最右边的

排序:插入排序及希尔排序

天涯浪子 提交于 2020-01-16 00:27:50
代码 #include < stdio.h > #define SIZE 11 void showarr( int [], int ); void insertsort( int [], int ); void insertsortV2( int [], int ); void shellsort( int [], int ); int main( void ){ int arr[SIZE] = { 0 , 10 , 4 , 7 , 2 , 1 , 8 , 32 , 20 , 80 , 6 }; // insertsortV2(arr,SIZE); // showarr(arr,SIZE); shellsort(arr,SIZE); return 0 ; } void showarr( int arr[], int size){ int i; for (i = 1 ;i < size;i ++ ){ printf( " %d, " ,arr[i]); if (i == size - 1 ){ printf( " \n " ); } } } void shellsort( int arr[], int size){ int n,i,j; printf( " please input n:\n " ); while (scanf( " %d " , & n) == 1 ){ if (

排序算法——希尔排序

社会主义新天地 提交于 2020-01-13 07:11:33
希尔排序 我对希尔排序进行学习的博客: 希尔排序–简单易懂图解 前言 可以说是一个加强版的插入排序。在插入排序中,最好的时间复杂度是 O ( N ) O(N) O ( N ) 可以说是极其舒服的线性时间复杂度,而这最好的情况,就是当数组中所有的数都是有序的时候,这是 O ( N ) O(N) O ( N ) 的复杂度。或者稍微比较好的情况,就是数组中大部分数都是有序的时候,那么,插入排序的时间复杂度,将趋近于 O ( N ) O(N) O ( N ) ,也就是线性的复杂度。而希尔排序的思想本质就是让数组中的数在尽可能少的次数内,变得有序起来,从而缩短整体时间复杂度,当然这思想没有脱离插入排序的基本做法,所以希尔排序的最坏时间复杂度,依然是 O ( N 2 ) O(N^2) O ( N 2 ) ,但在平均的情况下,希尔排序的时间复杂度将会是挺可观的。 基本做法 对数组进行分组(逻辑上的分组),然后对每个分组进行插入排序,使分组中的数变得有序,因为被分组后,每个分组中的数都不是很多,所以单次分组后的插入排序相对来说不会有过高的时间复杂度。然后经过多次分组然后执行插入排序后,数组中的数在整体上的有序程度会逐步拔高,直到最后一次对整体的插入排序,时间复杂度基本趋近于线性 O ( N ) O(N) O ( N ) 。而这个分组的依据就很关键了,在希尔排序中使用的则是与计算机紧密相关的数 2

基本排序算法--希尔排序随笔

喜你入骨 提交于 2020-01-11 02:39:24
基本思想 将整个序列按照相距某个“增量”进行拆分,然后逐个对子序列进行直接插入排序,使得得到的结果基本有序,最后对基本有序的序列进行一次直接插入排序,使得整个序列有序。 代码实现: /** * 希尔排序,间隔比较大的时候,排序次数比较少; * 间隔比较小的时候,移动距离比较短;由于跳着排,所以它不稳定 * * 首先给定一个间隔,按间隔选取元素,将选取好的元素排好序,如: * 【a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15】 * 【a0, a4, a8, a12】【a1, a5, a9, a13】【a2, a6, a10, a14】【a3, a7, a11, a15】 * * 然后将间隔按规则减小,在按间隔选取元素,重新排序号选取的元素, * 【a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15】 * 【a0, a2,a4, a6, a8, a10, a12, a14】【a1, a3, a5, a7, a9, a11, a13, a15】 * * 直到间隔为1,在按间隔选取元素并排序 * 【a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13,

C++ 希尔排序

我只是一个虾纸丫 提交于 2020-01-11 00:14:37
两个49在排序前后位置颠倒了,所以希尔排序是不稳定的 希尔排序是基于插入排序的以下两点性质而提出改进方法的: 1.插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。 2.但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。 希尔排序的基本思想是: 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。 设计思路: 1.首先用一个增量来分组,控制增量为一层循环 2.然后控制分组为1层循环,假如增量一开始为5,则分组为:第一组:0 5 15…第二组:1 6 11… 3.直接插入排序 注意这里是对这些分组进行直接插入排序 最后增量为1,就是对整个序列进行直接插入排序 # include <iostream> using namespace std ; //希尔排序 void shellSort ( int arrs [ ] , int len ) { for ( int d = len / 2 ; d >= 1 ; d = d / 2 ) { //控制增量 for ( int k = 0 ; k < d ; k ++ ) { //控制分组 for ( int i = k + d ; i < len ; i = i + d ) { //直接插入排序 //直接插入排序

希尔排序-java

风格不统一 提交于 2020-01-03 13:05:38
插入排序的一种,是缩小增量排序 直接插入排序,在数据比较有序的时候,插入的效率较高。当数据量大且数据不怎么有序的时候,直接插入排序的效率就比较低。 希尔排序就是在直接排序的基础上进行优化。 public static void shellSort(int[] arr) { int len = arr.length; int d; int i, j, k, min; for (d = len / 2; d >= 1; d /= 2) {//确定 for (i = 0; i < d; i++) {//确定有几组数据 for (j = i; j<len; j+=d) {//对分组之后的数据进行插入排序。(注意不是冒泡排序) min=arr[j]; for ( k = j-d; k >=0 ; k-=d) { if(arr[k]>min){ arr[k+d]=arr[k]; }else{ break; } } arr[k+d]=min; } } } } 来源: CSDN 作者: 羽绒333333 链接: https://blog.csdn.net/yurong33333/article/details/103817411

希尔排序(2)

情到浓时终转凉″ 提交于 2020-01-03 05:22:46
希尔(Shell)排序又称为 缩小增量排序 ,它是一种 插入排序 。它 是直接插入排序算法的一种威力加强版 。 希尔排序的 基本思想 是: 把记录按 步长 gap 分组,对每组记录采用 直接插入排序 方法进行排序。 随着 步长逐渐减小 ,所分成的组包含的记录越来越多,当步长的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序。 我们来通过演示图,更深入的理解一下这个过程。 在上面这幅图中: 初始时,有一个大小为 10 的无序序列。 在 第一趟排序中 ,我们不妨设 gap1 = N / 2 = 5,即相隔距离为 5 的元素组成一组,可以分为 5 组。 接下来,按照直接插入排序的方法对每个组进行排序。 在 第二趟排序中 ,我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2 = 2 (取整数)。这样每相隔距离为 2 的元素组成一组,可以分为 2 组。 按照直接插入排序的方法对每个组进行排序。 在 第三趟排序中 ,再次把 gap 缩小一半,即gap3 = gap2 / 2 = 1。 这样相隔距离为 1 的元素组成一组,即只有一组。 按照直接插入排序的方法对每个组进行排序。此时, 排序已经结束 。 需要注意一下的是,图中有两个相等数值的元素 5 和 5 。我们可以清楚的看到,在排序过程中, 两个元素位置交换 了。 所以,希尔排序是不稳定的算法。 public

面试准备(算法部分)

断了今生、忘了曾经 提交于 2020-01-03 04:58:40
No.1 冒泡排序 冒泡排序无疑是最为出名的排序算法之一,从序列的一端开始往另一端冒泡(你可以从左往右冒泡,也可以从右往左冒泡,看心情),依次比较相邻的两个数的大小(到底是比大还是比小也看你心情)。 冒泡排序动图演示 图解冒泡排序 以 [ 8,2,5,9,7 ] 这组数字来做示例,上图来战: 从左往右依次冒泡,将小的往右移动 冒泡排序1 首先比较第一个数和第二个数的大小,我们发现 2 比 8 要小,那么保持原位,不做改动。位置还是 8,2,5,9,7 。 指针往右移动一格,接着比较: 冒泡排序2 比较第二个数和第三个数的大小,发现 2 比 5 要小,所以位置交换,交换后数组更新为:[ 8,5,2,9,7 ]。 指针再往右移动一格,继续比较: 冒泡排序3 比较第三个数和第四个数的大小,发现 2 比 9 要小,所以位置交换,交换后数组更新为:[ 8,5,9,2,7 ] 同样,指针再往右移动,继续比较: 冒泡排序4 比较第 4 个数和第 5 个数的大小,发现 2 比 7 要小,所以位置交换,交换后数组更新为:[ 8,5,9,7,2 ] 下一步,指针再往右移动,发现已经到底了,则本轮冒泡结束,处于最右边的 2 就是已经排好序的数字。 通过这一轮不断的对比交换,数组中最小的数字移动到了最右边。 接下来继续第二轮冒泡: 冒泡排序5 冒泡排序6 冒泡排序7 由于右边的 2 已经是排好序的数字