博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
八大排序之插入排序(直接插入排序 & 希尔排序)
阅读量:2243 次
发布时间:2019-05-09

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

文章目录

插入排序

插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序可以分为直接插入排序和希尔排序。


直接插入排序

相信大家都玩过扑克牌(即使没玩过,也听说过)。

  • 当我们手里有第一张牌的时候,随便放
  • 当有第二张牌的时候,与第一张牌进行比较,比第一张大,放在它的后面,比一张小,放在它的前面
  • 当有第三张牌的时候,与前两张比较,选择位置插入
  • 以此类推

这就是插入,类比到我们排序中,就能得到如下步骤

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤2~5
    代码如下:
void InsertSort(int arr[], int size)	{
for (int i = 1; i < size; i++) //i表示当前要排序的数 {
int key = arr[i]; int j; for (j = i - 1; j >= 0; j--) //从i的前一个元素开始往前找 {
if (arr[j] > key) {
arr[j + 1] = arr[j]; } else {
break; } } arr[j + 1] = key; } }

时间复杂度:O(n ^ 2)

空间复杂度:O(1)
直接插入排序是稳定的
数组越有序,直接插入排序越快

二分插入排序

由于上述在查找比较关键码的时候,会比较慢。因为关键码前面已经有序,就可以运用二分查找的思想来判断关键码的位置。

void InsertSort(int arr[], int size)	{
for (int i = 1; i < size; i++) {
int tmp = arr[i]; //加入了一个二分查找的过程 int left = 0; int right = i - 1; while (left <= right) {
int mid = (left & right) + ((left ^ right) >> 1); if (arr[mid] > tmp) {
right = mid - 1; } else {
left = mid + 1; } } //这里一定要大于等于left,因为在上面left已经加1 for (int j = i - 1; j >= left; j--) {
arr[j + 1] = arr[j]; } arr[left] = tmp; } }

希尔排序

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。

因为直接插入排序依次只能移动一个数据,但如果要是依次可以移动多个数据,排序时间肯定就短了,于是便有了希尔排序。
基本思想:

  • 先将待排序序列分成若干个子序列(由相隔某个“增量”的元素组成的)
  • 将每个子序列进行直接插入排序
  • 将增量减1,再重复上述过程
  • 最终直到增量为1停止
    在这里插入图片描述
    代码如下:
void __InsertSort(int arr[], int size, int gap)	{
for (int g = 0; g < gap; g++) {
for (int i = g + gap; i < size; i += gap) {
int key = arr[i]; int j; for (j = i - gap; j >= 0; j -= gap) {
if (arr[j] > key) {
arr[j + gap] = arr[j]; } else {
break; } } arr[j + gap] = key; } } } void ShellSort(int arr[], int size) {
int gap = size; while (1) {
gap = gap / 3 + 1; __InsertSort(arr, size, gap); if (gap == 1) {
break; } } }

上述中gap = size / 3 + 1这是经过大量实验推算出来的,第一步的增量取这个值会更合理

虽然上述代码比较容易理解,但不够简洁。
优化:

void __InsertSort(int arr[], int size, int gap)	{
int j, key; for (int i = gap; i < size; i++) {
key = arr[i]; for (j = i - gap; j >= 0; j -= gap) {
if (arr[j] > key) {
arr[j + gap] = arr[j]; } else {
break; } } arr[j + gap] = key; } } void ShellSort(int arr[], int size) {
int gap = size; while (1) {
gap = gap / 3 + 1; __InsertSort(arr, size, gap); if (gap == 1) {
break; } } }

直接插入排序可以看做是增量为1的希尔排序


在这里插入图片描述

转载地址:http://adwdb.baihongyu.com/

你可能感兴趣的文章
Jmeter之参数化
查看>>
Shell 和Python的区别。
查看>>
【JMeter】1.9上考试jmeter测试调试
查看>>
【虫师】【selenium】参数化
查看>>
【Python练习】文件引用用户名密码登录系统
查看>>
学习网站汇总
查看>>
【Loadrunner】性能测试报告实战
查看>>
【自动化测试】自动化测试需要了解的的一些事情。
查看>>
【selenium】selenium ide的安装过程
查看>>
【手机自动化测试】monkey测试
查看>>
【英语】软件开发常用英语词汇
查看>>
Fiddler 抓包工具总结
查看>>
【雅思】雅思需要购买和准备的学习资料
查看>>
【雅思】雅思写作作业(1)
查看>>
【雅思】【大作文】【审题作业】关于同不同意的审题作业(重点)
查看>>
【Loadrunner】通过loadrunner录制时候有事件但是白页无法出来登录页怎么办?
查看>>
【English】【托业】【四六级】写译高频词汇
查看>>
【托业】【新东方全真模拟】01~02-----P5~6
查看>>
【托业】【新东方全真模拟】03~04-----P5~6
查看>>
【托业】【新东方托业全真模拟】TEST05~06-----P5~6
查看>>