博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[数据结构]插入排序与希尔排序
阅读量:6826 次
发布时间:2019-06-26

本文共 2559 字,大约阅读时间需要 8 分钟。

hot3.png

简述

直接插入排序是一种最简单的排序方法,基本操作是讲一个记录插入到已排好的有序数列中。

简单来说,将一乱序数列分成已排好和未排好两部分。每次从未排好部分取出一个数,将其插入到已排好的序列中去,其主要的复杂度消耗在插入位置的确定上。
直接插入是从头部或者尾部线性比较,当确定位置后,依次后移动一个记录。
对于插入位置的确定,可以使用二分查找方法确定。但是此方法只是减少了确定位置时的比较次数
(nlogn),但记录移动次数并未改动。

当序列基本有序或者待排序记录很少时,插入排序的性能非常好。

针对前者,引入了希尔排序,即在进行最后的直接插入排序前,可将数列进行预处理。将序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录基本有序时,在对全体序列进行一次直接插入排序。
希尔增量序列的取值对希尔排序的性能影响客观,其分析也是数学上的难题。不过应当注意的一点是,最后一趟排序其增量必须为1.

代码实例

#include
using namespace std;//前面提供两个辅助函数,一个二分查找函数,一个打印序列函数。int bin_search(int raw[], int begin, int end, int search){ //二分查找,返回被查找数应当放置的顺序位置 //n is the real length (do not include 0) int low = begin; int high = end; while (low <= high){ int mid = (low + high) / 2; if (search == raw[mid]) return mid; if (search < raw[mid]) high = mid - 1; if (search > raw[mid]) low = mid + 1; } //if not searched, low is the pos the searched number should placed //raw[low]is higher than search,raw[high] is lower than search; return low;}void dispList(int raw[], int n){ //from 1 to n not 0 to n for (int i = 1; i <= n; i++) cout << raw[i] << ' ';}void simpleInsertSort(int raw[], int n){ //简单直接插入排序 int temp, j; for (temp = 2; temp <= n; temp++){ raw[0] = raw[temp]; //raw[0]用作哨兵 for (j = temp - 1; raw[j]>raw[0]; j--) raw[j + 1] = raw[j]; //大的记录依次向后移动 raw[j + 1] = raw[0]; //移动后,将新的位置留给新进入的记录 }}void simpleInsertSort_Bin(int raw[], int n){ //简单二分插入排序 int temp, j; for (temp = 2; temp <= n; temp++){ raw[0] = raw[temp]; int pos = bin_search(raw, 1, temp - 1, raw[temp]); //pos返回的位置是二分查找后,其被查找结果对应的顺序位置。 for (j = temp - 1; j >= pos; j--){ raw[j + 1] = raw[j]; } raw[pos] = raw[0]; }}//以上是简单插入排序//如下给出希尔增量排序代码,其中增量序列随意取的,不具有优化意义。至于增量序列的取法这里不做讨论。void shellSort_basic(int raw[], int n, int step){    //每趟的排序部分。步长为step    //step is from a list for each loop,the last must be 1    int i, j;    for (i = 1 + step; i <= n; i++){        raw[0] = raw[i];        for (j = i - step; j>0 && raw[j]>raw[0]; j = j - step)//每次的步进单位都是step            raw[j + step] = raw[j];        raw[j + step] = raw[0];    }}void shellSort(int raw[], int n){    // this list should be careful set and must be end with 1    int step[3] = { 5, 3, 1 };//指定的增量序列    for (int i = 0; i<3; i++){        shellSort_basic(raw, n, step[i]);    }} void main(){ int a[9] = { 0, 3, 4, 8, 6, 7, 23, 21, 18 }; simpleInsertSort_Bin(a, 8); dispList(a, 8);}

复杂度分析:

对于插入排序,其在理想情况下达到O(n),在最坏情况下为O(n2)

对于希尔排序的复杂度分析较为复杂,不做分析。

总结:

对于记录不多和基本有序情况,插入排序是最实惠的排序方法。

希尔排序是插入排序的改进,希尔排序的增量序列选取很重要。
在序列中必须至少满足两点:
1,没有除了1以外的公因子。
2,最后一个数必须是1。

转载于:https://my.oschina.net/o0Kira0o/blog/278469

你可能感兴趣的文章
Linux - 修改内核启动顺序及删除无用内核
查看>>
kubernetes 健康检查和初始化容器
查看>>
es索引管理工具-curator
查看>>
Python+Django写一个本机性能监控应用?
查看>>
thinking in java
查看>>
Can not deserialize instance of java.lang.Integer out of START_ARRAY token
查看>>
矩阵按列按行归一化到L2范数的原理和最精简Matlab代码(转)
查看>>
如何方便的建立远程链接服务器
查看>>
Python自动化测试白羊座-week3文件操作
查看>>
centos安装jenkins
查看>>
JS合并两个数组的方法
查看>>
VBS将本地的Excel数据导入到SQL Server中
查看>>
ruby "==" "equal"
查看>>
JS 将数字转化成为货币格式
查看>>
cookie,session
查看>>
linux 定时任务
查看>>
iOS--动画--GitHub前50名的Objective-C动画相关库
查看>>
豆瓣电影
查看>>
如何扩展Orchard
查看>>
代码生成就用Razor模板
查看>>