数据结构之插入排序与希尔排序

1.直接插入排序

直接插入排序是一种最简单的排序算法,它的基本操作是将一个记录插入到已经排序好的序列中,从而得到一个新的有序表。直接插入排序算法原理如下图所示:

直接插入排序算法如下:

void InsertSort(int arr[],int length)
{
   int key,j;
   for(int i=1;i<length;++i)
   {
       key=arr[i];  //记录标志;

       j=i-1;

       //循环比较并且交换相邻的两个数;
       while (j>=0&&arr[j]>key)
       {
           arr[j+1]=arr[j];

           j=j-1;
       }
       arr[j+1]=key;
   }
}

插入排序的算法复杂度分析:从空间的角度来看,它需要一个记录的辅助空间,从时间的角度上来看,排序的基本操作:比较两个关键字的大小和移动记录。从算法中可以看出,for循环的次数取决于待插入关键字与前面i-1个关键字的关系。在整个排序过程中,当待排序的序列中记录按关键字按从小到大正序排列时,只需进行n-1次比较,比较次数达到最小值,记录不需要进行移动。反之,当待排序的序列是按逆序进行排列时,总的比较次数达到了最大值(n+2)(n-1)/2。记录移动的次数也达到了最大值(n+4)(n-1)/2。我们可以取最小值和最大值的平均值,则比较次数和移动记录次数约为n^2/4。因此,直接插入排序的算法复杂度为O(n^2)插入排序中相同的元素排序前后的位置不会发生改变,因此直接插入排序是一种稳定的排序方式。

2.希尔排序

希尔排序又称”缩小增量排序“它也属于插入排序类方法,但在时间效率上较前述直接插入排序方法有较大的改进。在进行插入排序时,如果全部是正序时,其时间复杂度为O(n)。

因此,如果待记录序列”基本有序“时,直接插入排序的效率可大大提高。希尔排序的基本思想:先将整个待排记录序列分割成为若干了子序列分别进行插入排序,待整个序列”基本有序“时,再对全体记录进行一次直接插入排序。希尔排序的过程如下图:

希尔排序的算法思路:先将要排序的一组记录按某个增量d(n/2,n为要排序数的个数)分成若干组子序列,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。继续不断缩小增量直至为1,最后使用直接插入排序完成排序。

希尔排序算法描述如下:

void ShellSort(int arr[],int length)
{
    int gap; //选择希尔排序的步长;

    //计算出希尔排序的次数;
    for (gap = length / 2; gap > 0; gap = gap / 2)
    {
        //进行gap次排序;
        for (int i = 0; i < gap; i++)
        {
            //一次插入排序;
            for (int j = i + gap; j < length; j = j + gap)
            {
                if (arr[j] < arr[j - gap])
                {
                    int temp = arr[j];
                    int k = j - gap;

                    while (k>=0&&arr[k]>temp)
                    {
                        arr[k + gap] = arr[k];
                        k = k - gap;
                    }
                    arr[k + gap] = temp;
                }
            }
        }
    }
}

希尔排序的算法复杂度计算是一个复杂的过程,到目前为止还未找到一种最好的”增量“序列函数。平均情况下希尔排序的算法复杂度为O(n^1.3)由于在希尔排序中会根据增量来进行局部排序,因此相同的元素在希尔排序前后位置会发生改变,因此希尔排序是一种不稳定的排序。

3.总结

排序算法是算法的基础,只有多了解算法的基础,才会对算法有更深的了解,本篇博客主要是为了更加深入的了解排序算法中的插入排序,如果有什么不妥之处,望大家多多指教。

时间: 2024-10-04 15:44:02

数据结构之插入排序与希尔排序的相关文章

数据结构例程——插入排序之希尔排序

本文是[数据结构基础系列(9):排序]中第3课时[插入排序之希尔排序]的例程. 1.希尔排序 #include <stdio.h> #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType key; //关键字项 InfoType data; //其他数据项,类型为InfoType } RecType; //排序的记录类型定义 void

数据结构精要------直接插入排序和希尔排序算法

上篇总结中主要实践了算法的内排序的选择排序,那么接下来我们继续实践插入排序排序的两种:直接插入排序和希尔排序算法. -----直接插入排序 package com.sort; /** * 直接插入排序 * * @author weixing-yang * * 算法思路: * 每步将一个待排序的元素,插入到前面已排序好的一组元素中的适当位置, * 直到所有元素全部出入完成为止. */ public class InsertionSort { public void insertionSort(in

【数据结构与算法】内部排序之一:插入排序和希尔排序的N中实现(不断优化,附完整源码)

转载请注明出处:http://blog.csdn.net/ns_code/article/details/20043459   前言 本来想将所有的内部排序总结为一篇博文,但是随着研究的深入,还是放弃了这个念头,斟前酌后,还是觉得分开来写比较好,具体原因,看完本篇博文也就自然明了了. 本篇文章主要探讨插入排序和希尔排序,之所将二者放在一起,很明显,是因为希尔排序是建立在插入排序的基础之上的.     注:以下各排序算法的N种实现方法大部分都是我根据算法思想,自己写出来的,或者是参考其本身的经典实

插入排序,希尔排序,堆排序,归并排序,快速排序Java实现

参看:数据结构与算法分析-c语言描述 public class Main { public static void main(String[] args) { String[] a = { "a", "d", "e", "f", "m" }; String[] b = { "a", "h", "g", "l", "z&

Python八大算法的实现,插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。

Python八大算法的实现,插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2).是稳定的排序方法.插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素).在第一部分排序完成后,再将这

插入排序 | 冒泡排序 | 希尔排序 | 堆排序 | 快速排序 | 选择排序 | 归并排序

以下是最近学习各种算法的代码实现: #include <stdlib.h> #include <stdio.h> #include <time.h> #include <limits.h> typedef int EleType; typedef int (*CompFunc)(void *,void *); int IntComp(void * a,void *b) { if(*(int *)a > *(int *)b) return 1; if(*

java排序之插入排序(直接插入排序和希尔排序)

上面一片博文探讨了关于的java选择排序(冒泡排序和快速排序)本章将继续探讨java排序之插入排序,插入排序分为直接插入排序和希尔排序两种. 1.直接插入排序思想:在需要排序的一组数据中假设前该数组的前n-1(n >= 2)个数是已经排好序的,现在要把第n个数插入到前面的n-1个数中,使得这n个数也是排好顺序的.如此反复进行,知道n等于需要排序的数组的长度时.就实现了该数组的直接插入排序. 代码如下: /** * * @param a 需要排序的数组 */ public static void

#排序算法#【2】直接插入排序、希尔排序

直接插入排序法 插入排序的算法描述是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后移动,为最新元素提供插入空间. 核心代码: //直接插入排序法 void InsertSort(int a[],int n){ int i,j,k,t; for(i = 1 ; i<n;i++){ k = a[i]; /* 第一次比较粗糙的写法 j = i-1; while(

插入排序,希尔排序,堆排序详解

本文将介绍三种排序算法--插入排序,希尔排序,堆排序.本文所有例子都是使用升序 一.插入排序 算法思想 维护一个有序数组,将要插入的数据与有序数组自最后一个元素直到合适位置的数一一比较. eg: 有序数组:1,3,5,6,7   现在待插入数据为2,那么他将会和7,6,5,3,依次作比较,当带插入数据小于有序数组最后的元素大小,则将该元素后移,直到待插入元素找到合适位置为止. 代码实现 void InsertSort(int* a, int size) 02 { 03     assert(a)