内部排序(一)插入排序

插入排序分为4种:

直接插入排序、折半插入排序、2-路插入排序、表插入排序、希尔排序。

下面我们来一一介绍:

直接插入排序

过程叙述:先将序列中的第1个记录看成是一个有序的子序列,然后从第二个记录起逐个进行插入,直至整个序列变成按关键字非递减有序序列为止。第i趟直接插入排序的操作为:将记录r[i]插入到有序子序列{r[1],r[2]……r[i-1]}中(自i-1起往前搜索,同时后移记录,直至找到插入点,进行插入),变成含有i个记录的有序子序列{r[1],r[2]……r[i-1]}。

注意:

1. 插入成功一个值为一趟。

2. 需要在r[0]处设置监视哨。

3. 整个排序过程进行n-1趟插入。

算法程序:

void InsertSort(SqList &L){
    //对顺序表L做直接插入排序(升序)
    for(i=2;i<=L.length;i++){
        if( L.r[i].key < L.r[i-1].key ){
            L.r[0]=L.r[i];//设置监视哨
            L.r[i]=L.r[i-1];//对r[i-1]进行后移
            for(j=i-2; L.r[0].key < L.r[j].key ;j--){
            //因为第一个if语句已经判断过r[i-1]和r[i](哨兵)的大
            //小,并进行后移操作,故此处从r[i-2]开始。j中最后存放要
            //插入点的下标。

                L.r[j+1]=L.r[j];//不符合条件,后移。
            }
            L.r[j+1]=L.r[0];//进行插入
        }
    }
}

评价

1.直接插入排序比较次数和移动次数约为(n^2)/4时间复杂度为O(x^2).

2.适用于n很小的情况。

折半插入排序

折半查找原理很简单,就是把直接插入排序过程中的直接查找过程用二分查找代替,即减少比较次数。

算法代码:

void BInsertSort(SqList &L){
//对顺序表L作折半插入排序。
    for(i=2;i<=L.length;i++){//将r[i]插入到r[i~(i-1)]的有序序列中
        L.r[0]=L.r[i];//设置监视哨
        low=1;
        high=i-1;
        while(low<=high){//找出插入点
            m=(low+high)/2;
            if( L.r[0].key < L.r[m].key){
                high=m-1;
            }else{
                low=m+1;
            }
        }

        for(j=i-1;j>=high+1;j--){
            L.r[j+1]=L.r[j];//记录后移
        }

        L.r[high+1]=L.r[0];//插入
    }
}

评价

1.折半插入排序仅减少了比较次数,而记录的移动次数不便。故时间复杂度依然为O(x^2)。

2.适用于n比较大时。

2-路插入排序

原理:

2-路插入排序是在折半插入排序的基础上再改进,目的是减少排序过程中移动记录的次数。为此需要n个记录的辅助空间。

过程叙述

另设置一个和L.r同类型的数组d,首先将L.r[1]赋值给d[1],并将d[1]看成是在排好序的序列中处于中间位置的记录,然后从L.r中第二个记录起依次插入到d[1]之前或之后的有序序列中。

通过一个辅助的循环数组, 如果大于最大的元素, 则插入至尾部, 如果小于最小的元素, 则插入至头部,

如果在两者之间, 采用折半查找的方式,移动一部分的元素;

演示

注意

  1. 把d看成一个循环数组。(所谓的循环数组并不是指它们真的首尾相接,而是指逻辑上循环。通过%完成)

    用(x+n)%n取代x,即可完成循环。

  2. 设置两个指针first和final分别指示排序过程中得到的有序序列中的第一个记录和最后一个记录在d中的位置。

算法程序

void TwoRoadInsertSort(int *arr, int *temp, int n)  {
//arr为原数组,temp为临时数组,n为数组长度

    int i, first, final, k;  

    first = final = 0;
    temp[0] = arr[0];//将arr首元素赋给temp  

    for (i = 1; i < n; i ++) {
        if (arr[i] < temp[first]) {  // 待插入元素比最小的元素小
            first = (first - 1 + n) % n;
            temp[first] = arr[i];
        } else if (arr[i] > temp[final]) { // 待插入元素比最大元素大
            final = (final + 1 + n) % n;
            temp[final] = arr[i];
        } else { // 插入元素比最小大,比最大小(此过程可自己在上面演示中最后添加元素26,走一遍)note:此处最好用折半查找!!!
            k = (final + 1 + n) % n;
            while (temp[((k - 1) + n) % n] > arr[i]) {
                temp[(k + n) % n] =temp[(k - 1 + n) % n];
                k = (k - 1 + n) % n;
            }
            temp[(k + n) % n] = arr[i];
            final = (fianl + 1 + n) % n;
        }
    }  

    // 将排序记录复制到原来的顺序表里
    for (k = 0; k < n; k ++) {
        arr[k] = temp[(first + k) % n];
    }
}  

评价

2-路插入排序首尾插入不需要移动元素。移动次数约为(n^2)/8,可以减少移动次数,并不能避免移动。

表插入排序

引入背景:在2-路插入排序的基础上再减少移动次数,直至不需要移动。

(未完待续……)

时间: 2024-12-11 02:15:39

内部排序(一)插入排序的相关文章

10-3-二路插入排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第10章  内部排序 - 2-路插入排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? SequenceListType.c        相关测试数据下载  链

10-2-折半插入排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第10章  内部排序 - 折半插入排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? SequenceListType.c        相关测试数据下载  链接

直接插入排序(内部排序)

1 package com.trfizeng.insertionsort; 2 3 /** 4 * 5 * @author trfizeng 内部排序 插入排序 --- 直接插入排序(Straight Insertion Sort) 6 * 7 */ 8 public class StraightInsertionSort { 9 public static int[] straightInsertionSort(int[] array) { 10 // 对传来的待排序数组进行合法验证 11 i

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

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

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

数据结构6种内部排序算法的比较

1.需求分析 (1)输入数据的形式为:伪随机数产生程序产生,且每次输入数不少于100个,至少要用5组不同的输入数据 (2)输出的形式为:输出关键字参加的比较次数和关键字的移动次数(关键字交换计为3次移动)的数据 (3)程序能达到的功能:对起泡排序,直接插入排序,简单选择排序,快速排序,希尔排序,堆排序这6种常用的内部排序算法进行比较,比较的指标为有关键字参加的比较次数和关键字的移动次数(关键字交换计为3次移动) (4)测试数据:正确输入为由伪随机数产生程序产生100个随机数,然后输出比较结果,错

几种内部排序-分类-复杂性-稳定性

1. 简述 本文主要说明一些常用的内部排序算法的分类.复杂性和稳定性.主要基于现在的理解和学习,详细准确的复杂度可以参见维基百科等比较权威的网站,对于一些算法的不同实现,复杂度也不同,这里给出的复杂度都是相对较好的算法的复杂度. 2. 分类    3. 复杂性和稳定性 冒泡排序:在已经有序的情况,取得O(N)的复杂度.    快速排序:每次递归都是N的复杂度,递归次数根据序列有关系,当已经有序的情况下,递归N次,时间复杂度为O(N*LogN)    插入排序:在已经有序的情况,取得O(N)的复杂

简单的选择排序(内部排序)

1 /** 2 * 3 */ 4 package com.trfizeng.selectionsort; 5 6 /** 7 * @author trfizeng 内部排序 选择排序—简单选择排序(Simple Selection Sort) 8 */ 9 public class SimpleSelectionSort { 10 11 /** 12 * 每次选择一个最小记录放在前面去 13 */ 14 public static int[] simpleSelectionSort(int[]

内部排序-第10章-《数据结构题集》习题解析-严蔚敏吴伟民版

//**留坑待填**// 一.基础知识题 10.1?以关键码序列(503,087,512,061,908,170,897,275,653,426)为例,手工执行以下排序算法,写出每一趟排序结束时的关键码状态: (1)直接插入排序:                            (2)希尔排序(增量d[1]=5): (3)快速排序:                                  (4)堆排序: (5)归并排序:                              

10-12-顺序表地址排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第10章  内部排序 - 顺序表地址排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? SequenceListType.c        相关测试数据下载  链